Это не вопрос, поскольку это больше известно. Я обновил приложение, которое использует 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). По-видимому, изменение значения этого числа изменяет значение вычисленного поплавка.