PHP7.1 json_encode () Float Issue

Это не вопрос, поскольку это больше известно. Я обновил приложение, которое использует json_encode() для PHP7.1.1, и я видел проблему с изменением поплавков, чтобы иногда расширять 17 цифр. Согласно документации, PHP 7.1.x начал использовать serialize_precision вместо точности при кодировании двойных значений. Я предполагаю, что это вызвало примерное значение

472,185

становиться

+472,18500000000006

после этого значение прошло через json_encode() . С момента своего открытия я вернулся к PHP 7.0.16, и у меня больше нет проблемы с json_encode() . Я также пытался обновить до PHP 7.1.2, прежде чем возвращаться к PHP 7.0.16.

Обоснование этого вопроса связано с PHP – Floating Number Precision , однако конец этой причине объясняется изменением точности использования serialize_precision в json_encode() .

Если кто-нибудь знает о решении этой проблемы, я был бы более чем счастлив услышать аргументы / исправить.

Выдержка из многомерного массива (до):

 [staticYaxisInfo] => Array ( [17] => stdClass Object ( [variable_id] => 17 [static] => 1 [min] => 0 [max] => 472.185 [locked_static] => 1 ) ) 

и после прохождения json_encode()

 "staticYaxisInfo": { "17": { "variable_id": "17", "static": "1", "min": 0, "max": 472.18500000000006, "locked_static": "1" } }, 

Это немного подтолкнуло меня, пока я наконец не нашел эту ошибку, которая указывает вам на этот RFC, который гласит:

В настоящее время json_encode() использует EG (точность), который установлен на 14. Это означает, что максимум 14 цифр используются для отображения (печати) номера. IEEE 754 double поддерживает более высокую точность, а serialize() / var_export() использует PG (serialize_precision), который по умолчанию должен быть более точным. Поскольку json_encode() использует EG (точность), json_encode() удаляет более низкие цифры частей дроби и разрушает исходное значение, даже если float PHP может содержать более точное значение float.

И (внимание мое)

Этот RFC предлагает ввести новую настройку EG (precision) = – 1 и PG (serialize_precision) = – 1, которая использует режим zend_dtoa () 0, который использует лучший алгоритм для округления чисел с плавающей запятой (-1 используется для указания режима 0) ,

Короче говоря, есть новый способ сделать PHP 7.1 json_encode использовать новый и улучшенный механизм точности. В php.ini вам необходимо изменить serialize_precision на

 serialize_precision = -1 

Вы можете проверить, работает ли она с этой командной строкой

 php -r '$price = ["price" => round("45.99", 2)]; echo json_encode($price);' 

Вы должны получить

 {"price":45.99} 

В качестве разработчика плагина у меня нет общего доступа к настройкам php.ini сервера. Поэтому, основываясь на ответе Machavity, я написал этот небольшой фрагмент кода, который вы можете использовать в своем PHP-скрипте. Просто поставьте его поверх скрипта, и json_encode будет работать как обычно.

 if (version_compare(phpversion(), '7.1', '>=')) { ini_set( 'serialize_precision', -1 ); } 

У меня была такая же проблема, но только serialize_precision = -1 не решила проблему. Я должен был сделать еще один шаг, чтобы обновить значение точности с 14 до 17 (как это было установлено в моем файле ini-файла PHP7.0). По-видимому, изменение значения этого числа изменяет значение вычисленного поплавка.