PHP7.1 json_encode () 플로트 문제
이것은 더 잘 알고 있기 때문에 질문이 아닙니다. json_encode()
PHP7.1.1 을 사용하는 응용 프로그램을 업데이트 했는데 부동 소수점이 때때로 17 자리를 확장하도록 변경되는 문제를 확인했습니다. 문서에 따르면 PHP 7.1.x는 serialize_precision
double 값을 인코딩 할 때 정밀도 대신 사용하기 시작했습니다 . 이로 인해 예제 값이 발생했다고 생각합니다.
472.185
될
472.18500000000006
그 값이 지나간 후에 json_encode()
. 내 발견 이후로 PHP 7.0.16으로 되 돌렸고 더 이상 json_encode()
. 또한 PHP 7.0.16으로 되돌리기 전에 PHP 7.1.2로 업데이트하려고했습니다.
이 질문의이면에있는 이유는 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()
는 14로 설정된 EG (precision)를 사용하고 있습니다. 이는 최대 14 자리 숫자가 숫자를 표시 (인쇄)하는 데 사용됨을 의미합니다. IEEE 754 개 배정 지원하는 높은 정밀도와는serialize()
/var_export()
PG (serialize_precision)가 17있는 세트를 더 정확하게하기 위해 기본값으로 사용합니다.json_encode()
EG (precision)를 사용 하기 때문에json_encode()
PHP의 float가보다 정확한 float 값을 보유 할 수 있더라도 분수 부분의 하위 자릿수를 제거하고 원래 값을 파괴합니다.
그리고 (내 강조)
이 RFC 는 zend_dtoa ()의 모드 0을 사용 하는 새로운 설정 EG (precision) =-1 및 PG (serialize_precision) = -1을 도입 할 것을 제안합니다.이 모드는 부동 소수점 수를 반올림하는 데 더 나은 알고리즘을 사용합니다 (-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 );
}
어떤 경우에는 변수를 하나 더 설정해야합니다. 두 번째 솔루션이 첫 번째 솔루션이 작동하는 것으로 입증 된 모든 경우에서 제대로 작동하는지 확실하지 않기 때문에 두 번째 솔루션으로 추가하고 있습니다.
if (version_compare(phpversion(), '7.1', '>=')) {
ini_set( 'precision', 17 );
ini_set( 'serialize_precision', -1 );
}
I had the same problem but only serialize_precision = -1 did not solve the problem. I had to do one more step, to update the value of precision from 14 to 17 (as it was set on my PHP7.0 ini file). Apparently, changing the value of that number changes the value of the computed float.
The other solutions didn't work for me. Here's what I had to add at the beginning of my code execution:
if (version_compare(phpversion(), '7.1', '>=')) {
ini_set( 'precision', 17 );
ini_set( 'serialize_precision', -1 );
}
I was encoding monetary values and had things like 330.46
encoding to 330.4600000000000363797880709171295166015625
. If you don't wish to, or can't, change the PHP settings and you know the structure of the data in advance there is a very simple solution that worked for me. Simply cast it to a string (both the following do the same thing):
$data['discount'] = (string) $data['discount'];
$data['discount'] = '' . $data['discount'];
For my use case this was a quick and effective solution. Just note that this means when you decode it back from JSON it will be a string since it'll be wrapped in double quotes.
I solved this by setting both precision and serialize_precision to the same value (10):
ini_set('precision', 10);
ini_set('serialize_precision', 10);
You can also set this in your php.ini
You could change the [max] => 472.185 from a float into a string ([max] => '472.185') before the json_encode(). As json is a string anyway, converting your float values to strings before json_encode() will maintain the value you desire.
As for me the problem was when JSON_NUMERIC_CHECK as second argument of json_encode () passed, which casting all numbers type to int (not only integer)
참고URL : https://stackoverflow.com/questions/42981409/php7-1-json-encode-float-issue
'IT TIP' 카테고리의 다른 글
Visio 2013에서 UML 다이어그램 셰이프 누락 (0) | 2020.12.04 |
---|---|
Objects.requireNonNull은 이전 방식보다 덜 효율적입니까? (0) | 2020.12.04 |
Ruby에서 언제`require`,`load` 또는`autoload`를 사용합니까? (0) | 2020.12.04 |
HTTP 응답을 보낸 후 계속 PHP 실행 (0) | 2020.12.04 |
DRY way to add created/modified by and time (0) | 2020.12.04 |