2010-11-19 3 views
0

가능한 중복 :이 X 미만 0.3PHP는 두 개의 동일한 수가 일치하지 않습니다. 곤충?

경우 $ 인 경우에만 1을 메아리

if($x <= .3) 
    echo 1; 

:


compare floats in php

내가 조건을 가지고 x가 .3 인 경우, 1을 얻지 못합니다.

,

은 내가 floatval()에있는 X를 포장하려했지만, 운이

내가는 $ X를 에코 시도하지 그리고 난 "0.3"

내가 if ($x == .3) 시도 얻을 - 난 경우 아무것도

을 시도했다 if (.3 == .3) 분명히 작동

어떤 아이디어? 이 PHP 버그입니까?

+1

이것은 버그가 아닙니다. 누군가가이를 닫으려면 사본을 찾아 주시겠습니까? –

+0

어떻게 $ x가 .3인지 알 수 있습니까? 전체 코드 $ x = .3; if ($ x <=. 3) echo 1? –

+0

$ x – erenon

답변

1

부동 소수점 값이 정확하지 않은 출력 :

는 그냥이 테스트. 당신은이 약이 같은 < = 0.3 있는지 확인할 수 있습니다 :

if ($x <= 0.3000001) { 
    echo 'yay'; 
} 
+0

와우 - 왜 그런가요? 그래서 12.8-12.5는 정말로 .3이 아닙니다. 나는 클라이언트와 확인해야하지만 잘하면 그는 2 자리 정확도로만 작업하고있다. – dan

+0

이것은 함께 진행됨에 따라 그 자체로 유능한 설명이다 : http://support.microsoft.co.kr/kb/42980 – dkamins

+0

BTW 당신이 정말로 궁금하지 않으면 왜 그 이유를 정확히 이해할 필요가 없습니다. 가장 중요한 점은 99 %의 시간, 부동 소수점 수를 정확도 연산자와 직접 비교해서는 안된다는 일반적인 규칙입니다. 정수는 물론 (바이너리로 직접 표현 될 수 있기 때문에) 물론 가능합니다. – dkamins

0

흠, 나는 $x이 실제로 .3과 같지 않다고 가정해야합니다.

<? 
    $var = 0.3; 

    if($var <= .3) 
    { 
     echo 'yay'; 
    } 
    else 
    { 
     echo 'boo'; 
    } 
?> 

그리고 yay

+0

물론 그렇지 않습니다. 0.3은 대부분의 컴퓨터에 실제로 존재할 수 없기 때문에. –

+0

이 작동하지만 내 변수는 실제로 작동하지 않는 $ x = 12.8-12.5에 의해 생성됩니다. – dan

0

$ X = 0.4;
if ($ x < = .3) {echo 1; }
잘 작동합니다. $ x에서 다른 값을 시도했습니다.
... $ x는 어디에서 얻습니까? 비교하기 전에 값을 "반올림"해야 할 수도 있습니다.

4

은 부동 소수점 숫자의 이진 표현에 대해 전부 :

var_dump(sprintf("%.40f", 0.3)); 
// string(42) "0.2999999999999999888977697537484345957637" 

는 기본적으로 0.3 정확히 기본 2에 표시 할 수없는, 그래서는 몇 가지 숫자 후 잘립니다. 기본적으로 기본 10 분의 1과 같습니다. 0.3을 입력 할 수 있지만 0.33은 더 정확합니다. 따라서 0.333, 0.3333 등입니다. 정확하게 표현할 수는 없습니다.

0

부동 소수점은 100 % 정확하지 않습니다. 요컨대, 분수 성분은 일반적으로 1/(2^n)을 더함으로써 저장된다. 예 : 1/2 + 1/4는 3/4이 저장되는 방식입니다. 그래서 이것은 버그가 아니며 특정 PHP 질문도 아닙니다.

그러나, 이것은 항상 진실해야합니다

$x = 0.3; 
if ($x == 0.3) echo "true"; 

을 같은 부정확성이 모두 존재하기 때문.

는 그러나 이것은 사실이 보장되지 :

if (abs($a - $b) < $delta) echo "true" 

델타는 매우 작은 숫자입니다 $ :이 델타를 사용하는 것입니다 주위에

$x = 0.1; 
$y = 0.2; 
if ($x + $y == 0.3) echo "true"; 

간단한 방법이 작동 할 수 있습니다.

정확성이 필요하면 BCMath 확장과 같은 것을 체크 아웃하십시오. 이 돈이면

은 다음 여기에 $ 1.23 = 123

1

하면, 큰, 빨간색과 지방을 어디로 단지, 전체 센트 (정수)에서 계산을 수행하려면 일반적으로 쉽게 : Floating Point Numbers :

단순한 십진수 인 0.1 또는 0.7과 같은 분수는 정밀도의 작은 손실없이 의 내부 이진수 대응 부품으로 변환 될 수 없습니다. 이 경우 결과가 혼동스럽게 이어질 수 있습니다. 플로어 ((0.1 + 0.7) * 10)는 내부 표현이 인 7.9와 같기 때문에 보통 대신 8을 반환합니다. 입니다.

숫자의 유한 번호를 10 진법으로 일부 분수 을 표현하는 불가능하다는 사실에 기인한다. 예를 들어, 소수 자릿수의 1/3은 0.3이됩니다.

숫자 부동 평등에 대한 부동 소수점 숫자를 비교 결코 마지막 자리에 및 결과 믿지 그래서 않았다. 더 높은 정밀도가 필요한 경우 arbitrary precision math functionsgmp 기능을 사용할 수 있습니다.

PS : 더 재미있다 :

INF == INF => false 
INF < INF => true 
INF > INF => true 

그래서 무한대 무한대 무한대하지 동시에 무한대보다 작고 무한대보다 더 크다. 생각해 보면 실제로 의미가 있습니다.