I've stumbled across a weird bug/problem.
I have a MySQL table with a column filled with numbers (BIGINT). These numbers are too big for a regular 32 bit integer, so PHP will cast them to a string on 32-bit. This gives the correct result every time.
When run on 64 bit PHP and not forcibly cast to a string with $variable = (string)$variable
, the result will sometimes be decremented by 1, such that a number like 1293203059233 becomes 1293203059232. This is no good obviously. The odd thing is that I cannot see any pattern.
It does not happen randomly such that one row from MySQL is decremented sometimes and sometimes not, but such that the same integers/rows are always decremented, and always by 1.
What could cause this? I use json_encode
to convert stdClass
-objects or arrays()
to text, then send them by regular HTTP responses.
The rows are retrieved by mysqli
using prepared statements such as :
$stmt = $sql->prepare->("SELECT BIGNUMBER FROM table WHERE SOMEID = ?");
$stmt->bind_result($bignumber);
$stmt->bind_param("i",$someid);
$stmt->execute();
$stmt->fetch();
$stmt->close();
$obj = new stdClass();
$obj->number = $bignumber;
echo json_encode($obj);
I have verified that all the integers are correct when browsing the database table.
Some examples (these are the actual values):
without cast to string:
10205160559939609 -> 10205160669939608 // bad
with:
10205160559939609 -> "10205160559939609" // good
without cast to string:
10154493437278508 -> 10154493437278508 // good (?)
with:
10154493437278508 -> "10154493437278508" // good
Edit: I did a error_log test pre-json_encode to test, yielding:
as Strng: (used error_log((string)$number);)
10205160559939609
as int: (used error_log($number);)
10205160559939609
Which would indicate that php does get the correct value, and that the error occurs in either php json_encode or in the browser's decode method.
Simply typing in 10205150669939609 in the chrome console will give you the number 10205150669939608 printed out (rounding effect). I guess integers this big aren't valid in JS so neither should they be in JSON. I'd use strings if I had values that large.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With