sourcecode

PHP7.1 json_encode() 플로트 문제

copyscript 2022. 9. 21. 23:25
반응형

PHP7.1 json_encode() 플로트 문제

이것은 질문이 아니다. 왜냐하면 그것은 더 의식적이기 때문이다.를 사용하는 응용 프로그램을 업데이트했습니다.json_encode()PHP7.1.1로 변경되어 플로트가 17자리까지 확장되는 문제가 발생하고 있었습니다..1는 PHP 7.1.x를 사용하기 했습니다.serialize_precision★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★에 값의 으로 추측됩니다.

472.185

되기 위해

472.18500000000006

후, 그 은 「」를 했습니다.json_encode().0 PHP 7.0.16에 json_encode()또한 PHP 7.0.16으로 되돌리기 전에 PHP 7.1.2로 업데이트하려고 했습니다.

이 질문의 이면에 있는 이유는 PHP - Floating Number Precision에서 기인합니다.단, 이 모든 이유는 의 precision에서 serialize_precision 사용방법이 변경되었기 때문입니다.json_encode().

이 문제에 대한 해결책을 알고 있는 사람이 있다면 기꺼이 그 이유와 해결책을 듣고 싶습니다.

다차원 배열에서 발췌(이전):

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

                    )

리리 through json_encode()

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

RFC를 참조할 수 있는 버그가 발견될 때까지, 이것은 잠시 동안 나를 미치게 했다.

★★★★★json_encode()합니다.EG(정밀)는 14로 설정됩니다.즉, 최대 14자리 숫자가 숫자를 표시(인쇄)하는 데 사용됩니다.IEEE , IEEE 754는 serialize()/var_export()되어 있는PG(하고 있습니다.「 PG ( serialize _ precision ) 」디폴트는 17로 설정되어 있기 때문에 보다 정밀도가 높아집니다.★★json_encode()는 EG EG(정밀),json_encode()PHP의 float 값이 더 정확한 float 값을 유지할 수 있더라도 frunction 부분의 하위 자릿수를 제거하고 원래 값을 파괴합니다.

그리고 (내 것을 강조한다)

이 RFC에서는 zend_dtoa()의 모드 0을 사용하는 새로운 설정 EG(precision)=-1 및 PG(serialize_precision)=-1을 도입할 것을 제안하고 있습니다.이 모드에서는 반올림 플로트 번호(-1은 0 모드를 나타내기 위해 사용됩니다.

7.을 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 );
}

precision과 serialize_precision을 모두 같은 값(10):

ini_set('precision', 10);
ini_set('serialize_precision', 10);

php.ini에서도 설정할 수 있습니다.

금전적 가치를 부호화하면서 이런 것들이 있었어요.330.46, 「」에의330.4600000000000363797880709171295166015625PHP 설정을 변경하고 싶지 않거나 변경할 수 없는 경우, 데이터 구조를 미리 알고 있다면 매우 간단한 솔루션이 있습니다.스트링에 입력하기만 하면 됩니다(다음은 모두 같은 처리를 합니다).

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

제 사용 사례에서 이것은 빠르고 효과적인 해결책이었습니다.이는 JSON에서 다시 디코딩할 때 큰따옴표로 둘러싸여 문자열이 된다는 것을 의미합니다.

php 7.2.32에서는 솔루션은 php.ini로 설정됩니다.

precision=10
serialize_precision=10

저도 같은 문제가 있었는데 serialize_module = -1 만으로는 문제가 해결되지 않았습니다.(PHP7.0 ini 파일에 설정되어 있는) 정밀도 값을 14에서 17로 갱신하기 위해 한 단계 더 진행해야 했습니다.그 숫자의 값을 변경하면 계산된 플로트 값이 변경되는 것 같습니다.

$val1 = 5.5;
$val2 = (1.055 - 1) * 100;
$val3 = (float)(string) ((1.055 - 1) * 100);
var_dump(json_encode(['val1' => $val1, 'val2' => $val2, 'val3' => $val3]));
{
  "val1": 5.5,
  "val2": 5.499999999999994,
  "val3": 5.5
}

로서는 언제가 였습니까?JSON_NUMERIC_CHECK의 두 이 인수는 정수뿐만 을 intjson_model()에합니다.이 인수는 정수뿐만 아니라 모든 번호 유형을 int로 캐스팅합니다.

.number_format , , , 「 」json_encodeJSON_NUMERIC_CHECK★★★★

$foo = array('max' => number_format(472.185, 3, '.', ''));
print_r(json_encode($foo, JSON_NUMERIC_CHECK));

다음과 같은 이점을 얻을 수 있습니다.

{"max": 472.185}

이것에 의해, 송신원오브젝트내의 모든 수치 문자열이, 결과 JSON내의 수치로서 부호화 되는 것에 주의해 주세요.

은, 문제가 발생한다고 것 같습니다.serialize ★★★★★★★★★★★★★★★★★」serialize_precision다른 값으로 설정됩니다.14일 17일다되었습니다. 14로 설정하면 가 해결됩니다.serialize_precision1로 하다.

" " "serialize_precision PHP 7.1.0에서 -1로 변경되었으며, 이는 "이러한 숫자를 반올림하기 위한 향상된 알고리즘이 사용될 것"을 의미합니다.그러나 여전히 이 문제가 발생할 경우 이전 버전에서 PHP 구성 파일을 사용하고 있기 때문일 수 있습니다.(업그레이드 시 컨피규레이션파일을 보관하고 있을 가능성이 있습니다).

고려해야 할 또 다른 사항은 플로트 값을 사용하는 것이 타당한지 여부입니다.올바른 소수 자릿수를 항상 JSON에 유지하기 위해 숫자를 포함하는 문자열 값을 사용하는 것이 적절할 수도 있고 그렇지 않을 수도 있습니다.

같은 문제.PHP 7.4에서는 다른 솔루션을 사용해 보았지만, 이 조합만이 유효했습니다.

precision = 14
serialize_precision = 14

[ max ] = > 472 . float 를 json _ float 앞의 문자열([ max ] = > '472 . float' )로 변경할 수 있습니다.json은 문자열이기 때문에 float 값을 json_encode()보다 앞의 문자열로 변환하면 원하는 값이 유지됩니다.

언급URL : https://stackoverflow.com/questions/42981409/php7-1-json-encode-float-issue

반응형