This isn’t a question as it is more of a be aware. I updated an application that uses json_encode()
to PHP7.1.1 and I was seeing an issue with floats being changed to sometimes extend out 17 digits. According to documentation, PHP 7.1.x started to use serialize_precision
instead of precision when encoding double values. I’m guessing this caused an example value of
472.185
to become
472.18500000000006
after that value went through json_encode()
. Since my discovery, I have reverted back to PHP 7.0.16 and I no longer have the issue with json_encode()
. I also tried to update to PHP 7.1.2 before reverting back to PHP 7.0.16.
The reasoning behind this question does stem from PHP – Floating Number Precision, however the end all reason for this is because of the change from precision to serialize_precision usage in json_encode()
.
If anyone does know of a solution to this problem, I’d be more than happy to listen in on the reasoning/fix.
Excerpt from multidimensional array (before):
[staticYaxisInfo] => Array ( [17] => stdClass Object ( [variable_id] => 17 [static] => 1 [min] => 0 [max] => 472.185 [locked_static] => 1 ) )
and after going through json_encode()
…
"staticYaxisInfo": { "17": { "variable_id": "17", "static": "1", "min": 0, "max": 472.18500000000006, "locked_static": "1" } },
Advertisement
Answer
This drove me nuts for a bit until I finally found this bug which points you to this RFC which says
Currently
json_encode()
uses EG(precision) which is set to 14. That means that 14 digits at most are used for displaying (printing) the number. IEEE 754 double supports higher precision andserialize()
/var_export()
uses PG(serialize_precision) which set to 17 be default to be more precise. Sincejson_encode()
uses EG(precision),json_encode()
removes lower digits of fraction parts and destroys original value even if PHP’s float could hold more precise float value.
And (emphasis mine)
This RFC proposes to introduce a new setting EG(precision)=-1 and PG(serialize_precision)=-1 that uses zend_dtoa()’s mode 0 which uses better algorigthm for rounding float numbers (-1 is used to indicate 0 mode).
In short, there’s a new way to make PHP 7.1 json_encode
use the new and improved precision engine. In php.ini you need to change serialize_precision
to
serialize_precision = -1
You can verify it works with this command line
php -r '$price = ["price" => round("45.99", 2)]; echo json_encode($price);'
You should get
{"price":45.99}