Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to create "pretty" numbers?

my question is: is there a good (common) algorithm to create numbers, which match well looking user understood numbers out of incomming (kind of random looking for a user) numbers.

i.e. you have an interval from

130'777.12 - 542'441.17.

But for the user you want to display something more ...say userfriendly, like:

130'000 - 550'000.

how can you do this for several dimensions? an other example would be:

23.07 - 103.50 to 20 - 150

do you understand what i mean?

i should give some criteria as well:

  • the interval min and max should include the given limits.
  • the "rounding" should be in a granularity which reflects the distance between min and max (meaning in our second example 20 - 200 would be too coarse)

very much honor you'll earn if you know a native php function which can do this :-)

*update - 2011-02-21 *

I like the answer from @Ivan and so accepted it. Here is my solution so far:

maybe you can do it better. i am open for any proposals ;-).

/**
 * formats a given float number to a well readable number for human beings
 * @author helle + ivan + greg
 * @param float $number 
 * @param boolean $min regulates wheter its the min or max of an interval
 * @return integer
 */
function pretty_number($number, $min){
    $orig = $number;
    $digit_count = floor(log($number,10))+1; //capture count of digits in number (ignoring decimals)
    switch($digit_count){
        case 0: $number = 0; break;
        case 1:
        case 2: $number = round($number/10) * 10; break;
        default: $number = round($number, (-1*($digit_count -2 )) ); break;
    }

    //be sure to include the interval borders
    if($min == true && $number > $orig){
        return pretty_number($orig - pow(10, $digit_count-2)/2, true);
    }

    if($min == false && $number < $orig){
        return pretty_number($orig + pow(10, $digit_count-2)/2, false);
    }

    return $number;

}
like image 954
helle Avatar asked Feb 18 '11 16:02

helle


2 Answers

I would use Log10 to find how "long" the number is and then round it up or down. Here's a quick and dirty example.

echo prettyFloor(23.07);//20
echo " - ";
echo prettyCeil(103.50);//110

echo prettyFloor(130777.12);//130000
echo " - ";
echo prettyCeil(542441.17);//550000

function prettyFloor($n)
{
  $l = floor(log(abs($n),10))-1; // $l = how many digits we will have to nullify :)
  if ($l<=0)
    $l++;

  if ($l>0)
    $n=$n/(pow(10,$l)); //moving decimal point $l positions to the left eg(if $l=2 1234 => 12.34 )
  $n=floor($n);
  if ($l>0)
    $n=$n*(pow(10,$l)); //moving decimal point $l positions to the right eg(if $l=2 12.3 => 1230 )
  return $n;
}

function prettyCeil($n)
{
  $l = floor(log(abs($n),10))-1;
  if ($l<=0)
    $l++;
  if ($l>0)
    $n=$n/(pow(10,$l));
  $n=ceil($n);
  if ($l>0)
    $n=$n*(pow(10,$l));
  return $n;
}

This example unfortunately will not convert 130 to 150. As both 130 and 150 have the same precision. Even thou for us, humans 150 looks a bit "rounder". In order to achieve such result I would recommend to use quinary system instead of decimal.

like image 111
Ivan Avatar answered Oct 13 '22 18:10

Ivan


You can use php's round function which takes a parameter to specify the precision.

<?php
echo round(3.4);         // 3
echo round(3.5);         // 4
echo round(3.6);         // 4
echo round(3.6, 0);      // 4
echo round(1.95583, 2);  // 1.96
echo round(1241757, -3); // 1242000
echo round(5.045, 2);    // 5.05
echo round(5.055, 2);    // 5.06
?>
like image 35
Greg Avatar answered Oct 13 '22 19:10

Greg