convertir como castear php json precision php-7.1

como - PHP7.1 json_encode() Problema de flotación



convertir string a int php (6)

Como desarrollador de complementos, no tengo acceso general a la configuración de php.ini de un servidor. Entonces, basado en la respuesta de Machavity, escribí este pequeño código que puedes usar en tu script PHP. Simplemente colóquelo encima del script y json_encode seguirá funcionando como de costumbre.

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

En algunos casos es necesario establecer una variable más. Estoy agregando esto como una segunda solución porque no estoy seguro de si la segunda solución funciona bien en todos los casos en que la primera solución ha demostrado funcionar.

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

Esta no es una pregunta, ya que es más un cuidado. json_encode() una aplicación que usa json_encode() a PHP7.1.1 y vi un problema con los flotadores que se cambian para extender a veces 17 dígitos. Según la documentación, PHP 7.1.x comenzó a usar serialize_precision lugar de precisión al codificar valores dobles. Supongo que esto causó un valor de ejemplo de

472,185

convertirse

472.18500000000006

después de que ese valor pasó por json_encode() . Desde mi descubrimiento, he vuelto a PHP 7.0.16 y ya no tengo el problema con json_encode() . También intenté actualizar a PHP 7.1.2 antes de volver a PHP 7.0.16.

El razonamiento detrás de esta pregunta proviene de PHP - Precisión de número flotante , sin embargo, la razón final de todo esto se debe al cambio de precisión al uso de serialize_precision en json_encode() .

Si alguien sabe de una solución a este problema, estaría más que feliz de escuchar el razonamiento / solución.

Extracto de una matriz multidimensional (antes):

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

y después de pasar por json_encode() ...

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


Estaba codificando valores monetarios y tenía cosas como la codificación 330.4600000000000363797880709171295166015625 a 330.4600000000000363797880709171295166015625 . Si no desea o no puede cambiar la configuración de PHP y conoce de antemano la estructura de los datos, hay una solución muy simple que me funcionó. Simplemente tírelo a una cadena (los dos siguientes hacen lo mismo):

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

Para mi caso de uso, esta fue una solución rápida y efectiva. Solo tenga en cuenta que esto significa que cuando lo decodifique de JSON, será una cadena ya que estará entre comillas dobles.


Esto me volvió loco por un momento hasta que finalmente encontré este error que te señala a este RFC que dice

Actualmente, json_encode() usa EG (precisión) que se establece en 14. Eso significa que se usan 14 dígitos como máximo para mostrar (imprimir) el número. IEEE 754 double admite una mayor precisión y serialize() / var_export() usa PG (serialize_precision) que se establece en 17 por defecto para ser más preciso. Como json_encode() usa EG (precisión), json_encode() elimina los dígitos más bajos de las partes de fracción y destruye el valor original incluso si el flotante de PHP podría contener un valor flotante más preciso.

Y (énfasis mío)

Este RFC propone introducir una nueva configuración EG (precisión) = - 1 y PG (serialize_precision) = - 1 que usa el modo 0 de zend_dtoa () que usa un mejor algoritmo para redondear los números flotantes (-1 se usa para indicar el modo 0) .

En resumen, hay una nueva forma de hacer que PHP 7.1 json_encode use el nuevo y mejorado motor de precisión. En php.ini necesita cambiar serialize_precision a

serialize_precision = -1

Puedes verificar que funciona con esta línea de comando

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

Deberías conseguir

{"price":45.99}


Las otras soluciones no funcionaron para mí. Esto es lo que tuve que agregar al comienzo de la ejecución de mi código:

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


Puede cambiar [max] => 472.185 de un flotante a una cadena ([max] => ''472.185'') antes de json_encode (). Como json es una cadena de todos modos, la conversión de sus valores flotantes a cadenas antes de json_encode () mantendrá el valor que desee.


Tuve el mismo problema pero solo serialize_precision = -1 no resolvió el problema. Tuve que hacer un paso más, para actualizar el valor de precisión de 14 a 17 (como estaba configurado en mi archivo ini PHP7.0). Aparentemente, cambiar el valor de ese número cambia el valor del flotador calculado.