2
$a     = 100;
$b     = 3;
$test1 = $a/ $b;
$test2 = 33.333333333333;  // $test2 == $test1

var_dump(($test1 * $b));   // float(100)
var_dump(($test2 * $b));   // float(99.999999999999)

そのための説明はありますか?

4

3 に答える 3

5

100/3になります33.3-repeating

それを示す小数点値はありません。数学では、そのような数は通常、繰り返し値の上に小さなドットで表示されます。(ただし、このコード ボックスでそれを表示する方法がわかりません)。

このウィキの記事を参照して、さまざまな場所でそれらがどのように表されているかを確認し、ここで提供したより詳細な説明を参照してください。

ただし、ここの記事からの要約のスニペットは次のとおりです。

算術では、小数の繰り返しは有理数を表す方法です。したがって、数値の 10 進数表現は、ある時点で周期的になる場合、つまり無限に繰り返される有限の数字列がある場合、反復 10 進数 (または反復 10 進数) と呼ばれます。たとえば、1/3 = 0.3333333… または 0.3 の 10 進数表現 (「0.3 繰り返し」または「0.3 繰り返し」と呼ばれる) は、小数点の直後で周期的になり、1 桁のシーケンス「3」を無限に繰り返します。やや複雑な例は 3227/555 = 5.8144144144… です。この場合、10 進数表現は小数点以下 2 桁目で周期的になり、数字のシーケンス「144」が無限に繰り返されます。

さて、それがここでの問題の核心ですが、(他の2つの回答が指摘しているように)フロートは計算と比較の点で驚くほど不正確であることにも注意してください。このサイトをすばやく検索すると、float の内部表現に問題を抱えている少数の人々が明らかになります。主に、比較を行うときに予期しない動作が発生したためです。

float データ型に関する PHP の警告をよく読んでください- ここでも重要な部分をコピーしました:

さらに、0.1 や 0.7 のように、基数 10 の浮動小数点数として正確に表現できる有理数は、仮数のサイズに関係なく、内部で使用される基数 2 の浮動小数点数として正確に表現できません。したがって、精度をわずかに低下させることなく、内部のバイナリ対応物に変換することはできません。これは紛らわしい結果につながる可能性があります。たとえば、floor((0.1+0.7)*10) は通常、予想される 8 ではなく 7 を返します。これは、内部表現が 7.9999999999999991118....

于 2012-09-28T07:18:54.383 に答える
1

PHPからの情報

警告

浮動小数点精度

浮動小数点数の精度は限られています。システムにもよりますが、PHP は通常、IEEE 754 倍精度形式を使用します。これは、1.11e-16 のオーダーで丸められるため、相対誤差が最大になります。非初等算術演算はより大きな誤差を与える可能性があり、もちろん、いくつかの演算が複合されている場合は誤差の伝播を考慮する必要があります。

さらに、0.1 や 0.7 のように、基数 10 の浮動小数点数として正確に表現できる有理数は、仮数のサイズに関係なく、内部で使用される基数 2 の浮動小数点数として正確に表現できません。したがって、精度をわずかに低下させることなく、内部のバイナリ対応物に変換することはできません。これは紛らわしい結果につながる可能性があります。たとえば、floor((0.1+0.7)*10) は通常、予想される 8 ではなく 7 を返します。これは、内部表現が 7.9999999999999991118....

したがって、浮動小数点数の結果を最後の桁まで信頼しないでください。浮動小数点数が等しいかどうかを直接比較しないでください。より高い精度が必要な場合は、任意精度の数学関数と gmp 関数を使用できます。

上記の警告で述べたように、浮動小数点値が等しいかどうかをテストすることは、それらが内部的に表現される方法のために問題があります。ただし、これらの制限を回避して浮動小数点値を比較する方法があります。

浮動小数点値が等しいかどうかをテストするには、丸めによる相対誤差の上限が使用されます。この値は、マシン イプシロン(単位の丸め) と呼ばれ、計算で許容される最小の差です。

私の質問に時間を割いて答えてくれたすべての人に感謝します

于 2012-09-28T09:24:29.330 に答える
1

floatすべての をプロセッサで正確に表現できるわけではありません。$a/$bその一つです。

そう、$test1 != $test2本当です。

于 2012-09-28T07:20:22.683 に答える