3

私が走るとき:

for($o=1;$o<=655;$o++){ $r = $r+0.01; echo $r." ";}

ある時点で私は得る:

...4.29 4.3 4.31 4.32 4.33 4.34 4.35 4.36 4.37 4.38 4.39 4.4
4.41 4.42 4.4299999999999 4.4399999999999 4.4499999999999
4.4599999999999 4.4699999999999 ...

しかし、私が実行すると:

for($o=1;$o<=5;$o+=0.01){ echo $o." "; }

異常は次の場所から始まります。

4.34 4.35 4.36 4.37 4.38 4.3899999999999 4.3999999999999

forループの一部である加算とforループ内の加算に違いがあるのはなぜですか?

4

4 に答える 4

5

丸め誤差の驚異へようこそ。

0.01は、有限の2進数として正確に表現できるわけではないため、別の浮動小数点数に繰り返し加算すると、最終的に丸め誤差が発生します。

丸め誤差が発生する特定のポイントは、関係する数値の2進展開がどのように実行されて丸め誤差が発生するかによって異なります。

于 2012-11-07T23:17:11.410 に答える
1

浮動小数点演算では、値を正確に表すことはできません。ここを参照してください。

于 2012-11-07T23:17:23.533 に答える
1

数字の「.01」を64ビットIEEE754バイナリ浮動小数点に変換すると、結果は0.010000000000000000208166817117216851329430937767028809になります。$ rが0に設定され、この近似値.01が100回追加されると、追加中の追加の丸め誤差により、結果は1.0000000000000006661338147750939242541790008544921875になります。

ここで、$ rがこの値から1をわずかに超えてさらに増分され、$ oが開始値の正確に1から増分されると考えてください。まず、$rと$oは異なる値で始まるため、通常、後で異なる値になります。第二に、それらは異なるため、増分がそれぞれに追加されると、追加の丸めとは異なるエラーが発生します。このエラーは、強化またはキャンセルするために発生する可能性があり、$rまたは$oが多かれ少なかれ異なる原因になります。

最後に、PHPには、小数点以下2桁以上の数値を出力するかどうかを決定するためのいくつかの基準があります。おそらく、ある時点で、$rまたは$oの値は、小数点以下2桁の最も近い数値から十分に離れているため、PHPはより多くの桁を出力する必要があると判断します。上で説明したように、これは$rと$oの異なる時間に発生します。

于 2012-11-08T01:26:47.467 に答える
0

Round()関数を使用できます。これへのリンクは次のとおりです:http: //php.net/manual/en/function.round.php

于 2012-11-07T23:50:01.723 に答える