먼저 예를 살펴보세요.
<?php$a = 0.1;$b = 0.9;$c = 1; var_dump(($a+$b)==$c); var_dump(($c-$b)==$a);?>
$a+$b==$c는 true를 반환하고,
$c-$b==$a는 false를 반환하고, error
왜 이런 일이 일어나는 걸까요?
연산 후 정밀도가 20자리일 때 실제 반환되는 내용은 다음과 같습니다.
<?php$a = 0.1;$b = 0.9;$c = 1; printf("%.20f", $a+$b); // 1.00000000000000000000printf("%.20f", $c-$b); // 0.09999999999999997780?>
$c-$b는 0.09999999999999997780이므로 0.1과 비교하면 false
이 문제가 발생합니다. 정밀도 부동 소수점 숫자를 이진수로 변환할 때 정밀도가 손실될 수 있습니다.
정수 부분은 2로 나누어 반올림방법
소수 부분은2를 곱하여 반올림방법
예: 숫자 8.5를 다음으로 변환합니다. 이진
정수 부분 8
8/2=4 8%2=0
4/2=2 4%2=0
2/2=1 2%2=0
1은 2보다 작으므로 계산할 필요가 없습니다. 정수는 8입니다. 이진법은 1000
소수 부분은 0.5
0.5x2 = 1.0
반올림 후의 소수 부분은 0이므로 더 이상 계산할 필요가 없습니다
십진수 0.5의 이진법은 0.1
8.5 1000.1
숫자 0.9의 이진수 표현을 계산하세요.
0.9x2=1.8
0.8x2=1.6
0.6x2=1.2
0.2x2=0.4
0.4x2=0.8
0.8x2=1.6
…. 그런 다음 사이클이 계속되고, 차단 정밀도가 N이면 N 다음의 숫자가 반올림되어 정밀도가 손실됩니다.
위의 예에서는 바이너리로 변환하면 정밀도 0.9가 손실되어 비교 시 오류가 발생합니다.
그러므로 부동 소수점 숫자가 마지막 숫자까지 정확하다고 믿지 말고 두 부동 소수점 숫자가 같은지 비교하지 마세요.
1. 라운드 방식을 사용하여 처리한 후 비교
예:
<?php$a = 0.1;$b = 0.9;$c = 1; var_dump(($c-$b)==$a); // falsevar_dump(round(($c-$b),1)==round($a,1)); // true?>
2. 연산을 먼저 수행할 때 , 높은 정밀도를 사용하십시오. 계산 방법은 정확성을 잃지 않도록 보장할 수 있습니다.
bcadd
두 개의 고정밀도 숫자를 더합니다. bccomp
두 개의 고정밀도 숫자를 비교하여 -1,0,1을 반환합니다. bcp
두 개의 고정밀도 숫자를 더합니다. -정밀도 숫자 숫자 나누기bcmod
고정밀 숫자의 나머지를 구합니다bcmul
두 고정밀 숫자를 곱합니다bcpow
고정밀 숫자의 거듭제곱을 찾습니다bcpowmod
모듈러스를 찾습니다. 고정밀 숫자의 거듭제곱bcscale
구성 기본값 소수점 이하 자릿수는 Linux bc의 "scale="과 동일합니다. bc bcsqrt
고정밀 숫자의 제곱근을 구합니다bcsub
두 개의 고정밀 숫자를 뺍니다. 정밀 숫자예:
<?php$a = 0.1;$b = 0.9;$c = 1; var_dump(($c-$b)==$a); // falsevar_dump(bcsub($c, $b, 1)==$a); // true?>
이 문서에서는 PHP 부동 소수점 숫자 비교 방법에 대해 설명합니다. 더 많은 관련 내용을 보려면 PHP 중국어 웹사이트를 참조하세요.
관련 추천:
mysql을 통해 쿼리 결과를 csv로 내보내는 방법 설명php array_push와 $arr[]=$valuePHP를 사용하여 설정하는 방법 만료 시간이 있는 엄격한 제어 세션위 내용은 PHP 부동 소수점 숫자 비교 방법에 대한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!