2012-01-29 14 views
0

可能性の重複:
The accuracy of PHP float calculateがdo-ながら浮かべ指数は言う:0.8 <0.8

<?php 
    $foo = 0; 
    do { 
     echo "\$foo = $foo".($foo >= 0.8 ? " >= 0.8<br>\n" : " < 0.8<br>\n"); 
     $foo = $foo + 0.1; 
    } while($foo <= 1); 
?> 

は、次の出力につながる:

$foo = 0 < 0.8 
$foo = 0.1 < 0.8 
$foo = 0.2 < 0.8 
$foo = 0.3 < 0.8 
$foo = 0.4 < 0.8 
$foo = 0.5 < 0.8 
$foo = 0.6 < 0.8 
$foo = 0.7 < 0.8 
$foo = 0.8 < 0.8 
$foo = 0.9 >= 0.8 
$foo = 1 >= 0.8 

を..でもvar_dumpはそれ以上0.8とは言わない。怖い:

round($foo,1) >= 0.8 

は、問題を解決します - 感謝助けて!

答えて

2

<?php 
$foo = 0; 

do { 
    echo sprintf('%.16f %s 0.8', $foo, $foo >= 0.8 ? '>=' : '<') . PHP_EOL; 
    $foo = $foo + 0.1; 
} while($foo <= 1); 

0.0000000000000000 < 0.8 
0.1000000000000000 < 0.8 
0.2000000000000000 < 0.8 
0.3000000000000000 < 0.8 
0.4000000000000000 < 0.8 
0.5000000000000000 < 0.8 
0.6000000000000000 < 0.8 
0.7000000000000000 < 0.8 
0.7999999999999999 < 0.8 
0.8999999999999999 >= 0.8 
0.9999999999999999 >= 0.8 

http://ideone.com/ggbMl

囲碁の図を生成し、あなたはあなたに応じて、ラウンド使用することができます


) rケース。しかし、典型的な解決策は、いわゆるmachine epsilonを使用しています。あなたの条件は、あなたのEPSの値

define ('EPS', 1e-15); 
if (abs($foo - 0.8) < EPS) { 
    // ... 

になり、ご使用のプラットフォームに明らかに依存するが条件で使用される値はまた、各操作がより多くの丸めエラーの原因として、数にやった算術演算の数によって異なります。詳細は、wikiの記事を参照してください。

+1

この小さなレッスンには大変感謝しています; – s10z

+0

あなたは大歓迎です) – Czechnology

+0

+1完全な答え(これについても考えましたが、私はPHPに精通していないので、アドバイス) – schnaader

2

ただ、標準の浮動小数点の丸めの問題。

典型的なフロート・ツー・ストリング変換は最下位のバイナリディジットを捨て、そう0.8として表示される2つの番号は、必ずしも同一ではありません。また、0.8は2進浮動小数点を使用して表現できないため、どちらも正確に0.8です。

2

問題は、あなたが正確にバイナリ浮動小数点で0.8を表すことができないということです。 0.1を正確に表すことはできません。したがって、0.8を計算するために不正確な値0.1を使用すると、不正確な値0.8に一致する可能性は低くなります。

+0

私はまだ道仕組みについてあまり理解していないドン。 round()を使わずに小数点を使って小文字を使用する方法はありますか? – s10z

+0

@Sascha Schulz、私の答えの最後を見てください。 IMO重複質問に言及 – Czechnology

+1

@hakreはコメントとして投稿し、誰かの他の人の答えに編集されてはいけません。 – CodesInChaos

3

floating point accuracy problem。あなたが考えるのは0.8ですが、コンピュータにはまったく0.8ではありません(彼は0.8を出力するかもしれませんが)。他の回答を補うために

関連する問題