2012-03-03 12 views
1

가능한 중복 :
Strange addition of numeric strings in PHP이상한 행동

$r = 1.0 - 0.8 - 0.2; 
var_dump($r); 

나는 플로트 -5.5511151231258E-17를 얻을. C++과 C#에서 얻은 결과와 동일한 결과입니다. 내가 얻을

MySQL은 쿼리를 통해 0.0 결과 :

SELECT 1.0 - 0.8 - 0.2 
+0

* 일반 참조 질문 * http://php.net/manual/en/language.types.float.php – NikiC

+0

또한 : HTTP : //en.wikipedia. org/wiki/Floating_point # Accuracy_problems – Leigh

답변

8

는 분명히하자 : 0.8이 값 8/10¹을 가지고 있기 때문에 소수의 유한 한 표현이있다.

2 진수에서는 값이 1/2 + 1/4 + 0/8 + 0/16 + 1/32 + 1/64 + 0/128 + ...이며 끝이 없습니다. 같은 삼분의 바이너리 표현으로 부동 소수점 값 3.

0.8 = 0.110011001100110011001100... in binary 
0.2 = 0.001100110011001100110011... in binary 

컴퓨터에 저장을 진수 표현 (0.333…)에는 끝이 없지만 기본에 0.1이 될 것입니다. 따라서 숫자를 더하거나, 빼거나, 곱하기 등의 정밀도가 떨어집니다.

C++, C 및 C#은 컴파일 된 언어이며 부동 소수점은 일반적으로 4 또는 8 바이트에 저장됩니다. 플로트에 0.8을 저장할 수 없습니다.

MySQL은 계산 결과를 잘라 내기 때문에 0이라고 말할 수도 있습니다.

모든베이스에서 정밀도를 잃지 않고 계산을 수행하는 라이브러리를 원하면 GMPlib를 찾아보십시오.

3

BCMath (이 경우에는 bcsub())을 사용하여 피할 수 있습니다. 또는 단순히 round() 일 수 있습니다 (두 번째 인수에서 정밀도를 설정할 수 있습니다). 모든 경우에 대해 -0을 받게되며 긍정적 인 경우 0을 사용하면 abs() 만 사용됩니다.

내가 무엇을 말하는지보기 here.

코드 예제 :

<?php 

    echo 'Direct: ' . (1.0 - 0.8 - 0.2) . '<br/>'; 

    echo 'BC Math: ' . bcsub(bcsub('1.0', '0.8'), '0.2') . '<br/>'; 
    echo 'Round: ' . round(1.0 - 0.8 - 0.2) . '<br/>'; 
    echo 'Absolute: ' . abs(round(1.0 - 0.8 - 0.2)) . '<br/>'; 

?>