 # Formatting a number to always and only show 3 digits

Hi there,

I’ve ran into a problem recently that I cannot solve for myself. I’ve got a range of numbers from 0 to 1trillion (1,000,000,000,000.00) and I need to format them to always show 3 digits, but at the same time no more than 3.

example:

```12.34 --> 12.3 1,234.56 --> 1.23k 2,345.67 --> 2.35k 12,345,678.00 --> 12.3m 123,456,789,012.00 --> 123b```

my first attempt was with a simple round()
[php]if ( \$isk < 1000 ) {
\$isk = number_format ( \$isk, 0 );
} elseif ( ( \$isk/1000 ) < 1000 ) {
if ( \$isk/1000 >= 99 ) {
\$isk = round ( ( \$isk/1000 ), 0 ) . “k”;
} elseif ( \$isk/1000 >= 9 ) {
\$isk = round ( ( \$isk/1000 ), 1 ) . “k”;
} else {
\$isk = round ( ( \$isk/1000 ), 2 ) . “k”;
}
} elseif ( ( \$isk/1000/1000 ) < 1000 ) {
if ( \$isk/1000/1000 >= 99 ) {
\$isk = round ( ( \$isk/1000/1000 ), 0 ) . “m”;
} elseif ( \$isk/1000/1000 >= 9 ) {
\$isk = round ( ( \$isk/1000/1000 ), 1 ) . “m”;
} else {
\$isk = round ( ( \$isk/1000/1000 ), 2 ) . “m”;
}
}
[…][/php]

but as you can see that produces a lot of if/else code, which I wanted to avoid, if possible.

I’ve also tried “%.2F” with sprintf() but that doesn’t limit the output to 3 digits, same for number_format().

So I would be very grateful if someone could point me in the right direction to accomplish this task with a bit nicer solution than what I’ve come up with so far.

regards

Here’s what I came up with

[php]
// conversion function to return 3 digits
function convert_number(\$num) {
\$num = round(\$num, 3); // round number
\$decimal = strpos(\$num, ‘.’); // get position of decimal
\$pos = \$decimal > 2 ? 3 : 4; // cut at 4 if decimal position is greater than 2

``````return substr(\$num, 0, \$pos);
``````

}

// our values
\$values = array(
12.34,
1234.56,
2345.67,
12345678.00,
123456789012.00,
12323456789012.00,
);

echo “

```”;
foreach(\$values as \$value) {
switch(\$value) {
case \$value > 1000000000000:
echo \$value . " --> " . convert_number(\$value / 1000000000000) . “t\n”;
break;
case \$value > 1000000000:
echo \$value . " --> " . convert_number(\$value / 1000000000) . “b\n”;
break;
case \$value > 1000000:
echo \$value . " --> " . convert_number(\$value / 1000000) . “m\n”;
break;
case \$value > 1000:
echo \$value . " --> " . convert_number(\$value / 1000) . “k\n”;
break;
default:
echo \$value . " --> " . convert_number(\$value) . “\n”;
break;
}
}
echo “```
”;
[/php]

Output

``````12.34 --> 12.3
1234.56 --> 1.23k
2345.67 --> 2.34k
12345678 --> 12.3m
123456789012 --> 123b
12323456789012 --> 12.3t``````

Your code works almost perfect! That’s really great =D
I encountered 2 issues when testing tho, one of which I was able to solve myself.

```2 --> 2 0.1 --> 0.1```

I solved that by replacing the following code:
[php]//\$num = round(\$num, 3); // round number
\$num = sprintf("%.2F",\$num);[/php]

Works great but both codes have a rounding issue at “23.456 --> 23.4” which should read “23.5”, my guess is that it would be because you substr() the number after rounding it. Would it be possible to round the number again at the end or sth?

thank you very much so far.

regards

You are right I shouldn’t have used substr(). This should have proper rounding:

[php]
function convert_number(\$num) {
\$num = number_format(\$num, 2); // all numbers will have a decimal
\$decimal = strpos(\$num, ‘.’); // get position of decimal
\$decimals = 2; // default round to 2 decimals

``````// if length is too large change number of decimals
\$length = strlen(\$num);
if (\$length > 4) {
\$decimals = (\$decimal > 2 ? 0 : 1);
}
return number_format(\$num, \$decimals);
``````

}
[/php]

Output

``````1 --> 1.00
0.1 --> 0.10
12.34 --> 12.3
23.4568 --> 23.5
1234.56 --> 1.23k
2345.67 --> 2.35k
12345678 --> 12.4m
123456789012 --> 123b
12323456789012 --> 12.3t``````

I love you … no homo.

Thank you very much!

regards

one little thing I noticed: numbers equal to 1000 (or 1m) are not formatted correcly, they are given the wrong letter at the end. I altered the switch case sentence to >= instead of >

just wanted to point out, if others may want to use this function aswell.