php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #78606 Wrong calculation when dealing with bigint
Submitted: 2019-09-29 02:55 UTC Modified: 2019-09-29 15:58 UTC
From: marcelotpcruz at gmail dot com Assigned: cmb (profile)
Status: Not a bug Package: Math related
PHP Version: 7.3.10 OS: Windows/Unix
Private report: No CVE-ID: None
 [2019-09-29 02:55 UTC] marcelotpcruz at gmail dot com
Description:
------------
Using a 64 bit install on a 64 bit system:

Test script:
---------------
<?php

$someInt	= 36028797018963968;//2^55

echo $someInt . '<br>';
echo number_format($someInt, 10, '.', '') . '<br>';
$someInt-= 10;
if((PHP_INT_MAX + 1) === (PHP_INT_MAX + 2)) //This should be false
	echo 'This should never be echoed<br>';

echo number_format($someInt, 10, '.', '') . '<br>';//Value here is just $someInt minus 10

$maxInt	= PHP_INT_MAX;
echo $maxInt . '<br>';
echo ++$maxInt . '<br>';
echo --$maxInt . '<br>';//Should print 9223372036854775807

echo number_format(PHP_INT_MAX, 0, '.', '') . '<br>';//Should print 9223372036854775807

Expected result:
----------------
36028797018963968
36028797018963968.0000000000
36028797018963958.0000000000
9223372036854775807
9.2233720368548E+18
9223372036854775807
9223372036854775807

Actual result:
--------------
36028797018963968
36028797018963968.0000000000
This should never be echoed
36028797018963960.0000000000
9223372036854775807
9.2233720368548E+18
9.2233720368548E+18
9223372036854775808

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2019-09-29 08:32 UTC] cmb@php.net
-Status: Open +Status: Not a bug -Assigned To: +Assigned To: cmb
 [2019-09-29 08:32 UTC] cmb@php.net
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to report
a bug at http://bugs.php.net/how-to-report.php

See <https://www.php.net/manual/en/language.types.integer.php#language.types.integer.overflow>
and <https://www.php.net/manual/en/language.types.float.php>.
 [2019-09-29 15:31 UTC] marcelotpcruz at gmail dot com
Good day!

According to the manual:
"If the float is beyond the boundaries of integer (usually +/- 2.15e+9 = 2^31 on 32-bit platforms and +/- 9.22e+18 = 2^63 on 64-bit platforms other than Windows), the result is undefined, since the float doesn't have enough precision to give an exact integer result."

$someInt	= pow(2, 55);
echo $someInt . '<br>';
echo number_format($someInt-10, 0, '.', '');

$someInt	= (float)pow(2,55);
echo $someInt . '<br>';
$someInt	-= 10;
echo (int)$someInt . '<br>';

In the samples I'm using number_format with a 2^55(36028797018963968) - 10, on a 64 bit system, shouldn't it give me 36028797018963958 instead of 36028797018963960?
Maybe the docs need to be updated or this looks like a bug.
 [2019-09-29 15:58 UTC] cmb@php.net
The quote you've cited is from the section "Converting to integer
– From floating point numbers"[1] and as such is irrelevant here.
What is relevant is that integral floats are not exact beyond ~
2**53 (assuming IEEE 754 doubles).  Also note that number_format()
expects a float, and if you're passing an int, it is converted to
float.

[1] <https://www.php.net/manual/en/language.types.integer.php#language.types.integer.casting.from-float>
 
PHP Copyright © 2001-2020 The PHP Group
All rights reserved.
Last updated: Wed Feb 19 13:01:30 2020 UTC