# 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;

}
``````

Maybe add some more examples? People seem to have trouble seeing what this is about

i think so too. have researched some days and nothing found.

Please explain your question more clearly: why do you want to round 23.07â€“103.50 to 20â€“150 and not to 20â€“105 or 20â€“110 or 10â€“110 or 0â€“120 or 0â€“150 etc.? What exactly is your criterion for numbers being "pretty"? Once you're clear about what you want, the solution should present itself.

@ShreevastaR well, i don't really know that. It should just be globally userfriendly ;-) ... too little steps would be not so pretty for me (20 - 105).

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(\$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(\$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.