Bug #74221 [Opn]: Float precision is altered when encoding to JSON for floats 0.99... and under

From: Date: Tue, 07 Mar 2017 23:06:15 +0000
Subject: Bug #74221 [Opn]: Float precision is altered when encoding to JSON for floats 0.99... and under
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-207732@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=74221&edit=1 ID: 74221 Updated by: nikic@php.net Reported by: bryn at imgur dot com Summary: Float precision is altered when encoding to JSON for floats 0.99... and under Status: Open Type: Bug Package: JSON related Operating System: Ubuntu 16.04.2 LTS PHP Version: 7.1.2 Block user comment: N Private report: N New Comment: You can restore the previous behavior by setting serialize_precision to the value of precision, which is 14 by default. Alternatively and preferably, you can set serialize_precision to -1. In this case PHP will automatically determine the minimal precision necessary to still accurately represent the number. Previous Comments: ------------------------------------------------------------------------ [2017-03-07 22:49:10] bryn at imgur dot com Description: ------------ The change to using serialize_precision in json_encode() may have had some side affects. Floating point numbers under 1.0 get a different precision than other floating point numbers and the precision for those numbers can be unpredictable. I noticed that var_export() is behaving the in the same way, but that is far less critical because it's not used as a data exchange format. At the moment, I have a single workaround for a single case - When encoding a JSON object only dealing with the exact same precision values, setting serialize_precision to 2 gives the expected result. That won't work for objects with mixed precision though. Test script: --------------- <?php # Getting the precision on the cli seems to change it. # Before these two lines were added, I was getting 53 points of precision. # After, it adhered to the value for serialize_precision and stayed there. #print 'Precision is set to '.ini_get('precision').PHP_EOL; #print 'Serialize Precision is set to '.ini_get('serialize_precision').PHP_EOL; $data = array( 0.35, (float)0.35, round(0.35, 2), 0.15, 1.25, 1.23, 1.0, 0.9, 4, ); print 'var_export: '.PHP_EOL.var_export($data, 1).PHP_EOL; print 'json_encode: '.PHP_EOL.json_encode($data, JSON_PRESERVE_ZERO_FRACTION).PHP_EOL; print 'print_r'.PHP_EOL; print_r($data); Expected result: ---------------- var_export: array ( 0 => 0.35, 1 => 0.35, 2 => 0.35, 3 => 0.15, 4 => 1.25, 5 => 1.23, 6 => 1.0, 7 => 0.9, 8 => 4, ) json_encode: [0.35,0.35,0.35,0.15,1.25,1.23,1.0,0.9,4] print_r Array ( [0] => 0.35 [1] => 0.35 [2] => 0.35 [3] => 0.15 [4] => 1.25 [5] => 1.23 [6] => 1 [7] => 0.9 [8] => 4 ) Actual result: -------------- var_export: array ( 0 => 0.34999999999999997779553950749686919152736663818359375, 1 => 0.34999999999999997779553950749686919152736663818359375, 2 => 0.34999999999999997779553950749686919152736663818359375, 3 => 0.1499999999999999944488848768742172978818416595458984375, 4 => 1.25, 5 => 1.229999999999999982236431605997495353221893310546875, 6 => 1.0, 7 => 0.90000000000000002220446049250313080847263336181640625, 8 => 4, ) json_encode: [0.34999999999999997779553950749686919152736663818359375,0.34999999999999997779553950749686919152736663818359375,0.34999999999999997779553950749686919152736663818359375,0.1499999999999999944488848768742172978818416595458984375,1.25,1.229999999999999982236431605997495353221893310546875,1.0,0.90000000000000002220446049250313080847263336181640625,4] print_r Array ( [0] => 0.35 [1] => 0.35 [2] => 0.35 [3] => 0.15 [4] => 1.25 [5] => 1.23 [6] => 1 [7] => 0.9 [8] => 4 ) ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=74221&edit=1

« previous php.bugs (#207732) next »