4

The following code gives me two different outputs:

$number = '1562798794365432135246';
echo $number; 
echo number_format($number);

Can anyone explain this?

EDIT: forgot to mention, the above gives me "1562798794365432135246 1,562,798,794,365,432,233,984". Note the last six digits are completely different for no obvious reason (all i was asking it to do was insert thousand separators).

lasavior
  • 141
  • 1
  • 5
  • Regarding the down-voting, i hope people actually read the content of the question header: "why is the number VALUE changing..". Im well aware that number_format() adds commas, its what i intended, but the VALUE is changing (the last six digits). Even if PHP has an integer limit, you would expect that entire value of the number to change to the max INT. Instead only the last six digits are affected. – lasavior Aug 04 '11 at 16:32
  • 1
    My guess is that your number is too big to fit in an int, and is converted to a float. This results in the loss of precision you are seeing. – NullUserException Aug 04 '11 at 23:07

3 Answers3

5

number_format(), as stated by the PHP manual, converts a float into a string with the thousands groups with commas.

$number = '1562798794365432135246';
var_dump($number); // string(22) "1562798794365432135246"
var_dump(number_format($number)); // string(29) "1,562,798,794,365,432,233,984" 

If you're trying to cast a string to an integer, you can do so like this:

$number = (int) $number;

However, be careful, since the largest possible integer value in PHP is 2147483647 on a 32-bit system and 9223372036854775807 on a 64-bit system. If you try to cast a string like the one above to int on a 32-bit system, you'll assign $number to 2147483647 rather than the value you intend!

The number_format() function takes a float as an argument, which has similar issues. When you pass a string as an argument to number_format(), it is internally converted to a float. Floats are a little more complicated than integers. Instead of having a hard upper bound like an integer value, floats progressively lose precision in the least significant digits, making those last few places incorrect.

So, unfortunately, if you need to format long strings like this you'll probably need to write your own function. If you only need to add commas in the thousands places, this should be easy - just use strlen and substr to get every set of three characters from the end of string and create a new string with commas in between.

Chris Hepner
  • 1,552
  • 9
  • 16
  • Though we are talking about PHP here, so casting is probably useless. – NullUserException Aug 04 '11 at 04:31
  • 1
    got confused with `number_output()`, shouldn't that be `number_format`? – tradyblix Aug 04 '11 at 04:43
  • @tradyblix Yes, it definitely should. Thanks! – Chris Hepner Aug 04 '11 at 04:50
  • Ok, i have concept of Type Casting as i was messing around with it in trying to get this to work because as an INT it was giving the wrong strlen() (which is now explained by the max INT you spoke of). i did not however know that there was a cap of integer values in PHP. Just seems odd to me as computers are very adept at computating numbers.. its what they do.. and yet theres a limit? Anyways, doesnt really explain that in the original question outputs the same size number, just the last six digits are different. thats the part i cant understand. I guess i have to go with Jacek's suggestion – lasavior Aug 04 '11 at 16:36
  • Yep, the processor only has so much space to store that information in - doing computations with values larger than it can read "in one go" take a lot more effort on its part. I see now I didn't really answer the actual question - I added a little information about floats (integers aren't really relevant here). Hope that helps. – Chris Hepner Aug 04 '11 at 16:55
  • hmm.. interesting. So much to know, its easy to see why places like stackoverflow are needed. thanks for the added info, greatly appreciated. it was late and i was pulling my hair out trying to understand it, i guess i'll just have to parse it myself. – lasavior Aug 04 '11 at 17:05
3

I know this is an old question, but I came across this issue recently and coded a function that works for my purpose. Hopefully it helps others. It works with single quote strings and $_GET. I haven't tested $_POST. Modifications will have to be made if you are dealing with negative integers or non integers.

<?php
function format_big_numbers($number, $delimiter) {
$len = strlen($number);
if ($len > 3){
    if ($len % 3 == 0) {
        $split = str_split($number, 3);
        $number_with_commas = implode("$delimiter", $split);
        return $number_with_commas;
    }
    else if ($len % 3 == 1) {
        $front = substr($number, 0, 1);
        $split = substr($number, 1, $len - 1);
        $split = str_split($split, 3);
        $number_with_commas = implode("$delimiter", $split);
        $number_with_commas = $front . "$delimiter" . $number_with_commas;
        return $number_with_commas;
    }
    else {
        $front = substr($number, 0, 2);
        $split = substr($number, 2, $len - 2);
        $split = str_split($split, 3);
        $number_with_commas = implode("$delimiter", $split);
        $number_with_commas = $front . "$delimiter" . $number_with_commas;
        return $number_with_commas;
    }
}
else {
    return $number;
}
}
$num = '1234567891234567891234567891234'; 
echo format_big_numbers($num, ","); // output is 1,234,567,891,234,567,891,234,567,891,234
?>
1

To work with PHP and such big numbers, You should use some library Working with large numbers in PHP

BC Math - http://www.php.net/manual/en/book.bc.php, GMP - http://www.php.net/manual/en/book.gmp.php

Community
  • 1
  • 1
Jacek Kaniuk
  • 5,229
  • 26
  • 28