PHP7.1 закодировать в JSON() вопрос поплавка



Это не вопрос, так как это скорее осознание. Я обновил приложение, которое использует 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"
}
},
613   5  

5 ответов:

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

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

И (курсив мой)

В этом документе предлагается ввести новый параметр например, (точность)=-1 и ПГ(serialize_precision)=-1, что использует zend_dtoa()'ы режим 0, который использует лучше algorigthm для округления числа с плавающей точкой (-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 (как это было установлено в моем файле PHP7.0 ini). По-видимому, изменение значения этого числа изменяет значение вычисляемого поплавка.

Другие решения не сработали для меня. Вот что мне пришлось добавить в начале выполнения кода:

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

Я кодировал денежные ценности и имел такие вещи, как 330.46 кодирование в 330.4600000000000363797880709171295166015625. Если вы не хотите или не можете изменить настройки PHP, и вы заранее знаете структуру данных, есть очень простое решение, которое сработало для меня. Просто приведите его к строке (оба следующие делают то же самое):

$data['discount'] = (string) $data['discount'];
$data['discount'] = '' . $data['discount'];

Для моего случая использования это было быстрое и эффективное решение. Просто обратите внимание, что это означает, что когда вы декодируете его обратно из JSON, это будет строка, так как она будет обернута в double двойные кавычки.

Comments

    Ничего не найдено.