부동 소수점 연산 정확도 문제
먼저 예를 살펴보세요:
<code><span><span><?php</span><span>$a</span> = <span>0.1</span>; <span>$b</span> = <span>0.9</span>; <span>$c</span> = <span>1</span>; var_dump((<span>$a</span>+<span>$b</span>)==<span>$c</span>); var_dump((<span>$c</span>-<span>$b</span>)==<span>$a</span>); <span>?></span></span></code>
$a $b== $c는 true를 반환하고, 맞음
$c-$b==$a는 거짓,오류
연산 후 정밀도가 20자리일 때 실제 반환되는 내용은 다음과 같습니다.
<code><span><span><?php</span><span>$a</span> = <span>0.1</span>; <span>$b</span> = <span>0.9</span>; <span>$c</span> = <span>1</span>; printf(<span>"%.20f"</span>, <span>$a</span>+<span>$b</span>); <span>// 1.00000000000000000000</span> printf(<span>"%.20f"</span>, <span>$c</span>-<span>$b</span>); <span>// 0.09999999999999997780</span><span>?></span></span></code>
$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.5x2 = 1.0
반올림 후 소수 부분이 0이므로 더 이상 계산할 필요가 없습니다
십진수 0.5의 이진법은 0.1입니다.
0.9x2=1.8
0.8x2=1.6
0.6x2=1.2
0.4x2=0.8 0.8x2=1.6 .... 그러면 루프가 계속됩니다. 차단 정확도가 N이면 N 이후의 숫자는 반올림되어 정확도가 손실됩니다. 위의 예에서는 이진수로 변환할 때 정밀도 0.9가 손실되어 비교 중에 오류가 발생합니다.
따라서 부동 소수점 숫자가 마지막 자리까지 정확하다고 절대 신뢰하지 말고, 두 부동 소수점 숫자가 같은지 비교하지 마세요.
부동소수점수를 정확하게 비교하는 방법
1. 라운드 방식으로 처리한 후 비교
예:
2. 고정밀 계산 방법을 사용합니다
고정밀 연산 방법은 다음과 같습니다.
bccomp는 두 개의 고정밀 숫자를 비교하고 -1,0,1을 반환합니다.
bcdiv는 두 개의 고정밀도 숫자를 나눕니다
bcmod는 고정밀 수치 나머지를 찾습니다
bcmul 두 개의 고정밀 숫자 곱하기
<code><span><span><?php</span><span>$a</span> = <span>0.1</span>; <span>$b</span> = <span>0.9</span>; <span>$c</span> = <span>1</span>; var_dump((<span>$c</span>-<span>$b</span>)==<span>$a</span>); <span>// false</span> var_dump(round((<span>$c</span>-<span>$b</span>),<span>1</span>)==round(<span>$a</span>,<span>1</span>)); <span>// true</span><span>?></span></span></code>bcpowmod는 고정밀 수치 거듭제곱과 계수를 찾습니다
bcscale은 Linux bc
의 "scale="과 동일한 기본 소수점 수를 구성합니다.
bcsqrt는 고정밀 숫자의 제곱근을 찾습니다
예:
저작권 표시: 이 기사는 블로거의 원본 기사이므로 블로거의 허가 없이 복제할 수 없습니다. 허가.
위 내용은 PHP 부동소수점 숫자 비교 방법을 내용적인 측면까지 포함하여 소개하고 있는데, PHP 튜토리얼에 관심이 있는 친구들에게 도움이 되었으면 좋겠습니다.