これはおそらく絶対エラーではなく相対エラーでイプシロンをチェックすることを可能にします。上記の例の値について
function areEqual(float $a, float $b) : bool {
return abs(($a - $b)/$b) < 0.00001;
}
areEqual(10000, 10000.01);
areEqual(0.0000001, 0);
ファクト:
は、これら2例の比較当社のイプシロンここで可能な最小イプシロンはとにかく、これらの値よりもはるかに小さい利便‐ため0.00001
であるが、それでは、この事実を無視してみましょう。我々のアルゴリズムでは、$a
と$b
はどちらも似ていると仮定しているため、$a
で割るか$b
で割るかは関係ありません。実際には、10000
はそれよりもはるかに大きく(非常に大きな指数)、0.0000001
ははるかに小さくすることはできますが、便宜上、これらが問題を引き起こす可能性のある値であるとしましょう。
ここでは既に違いを確認できます。
多数の場合:比較された浮動小数点が非常に大きい場合、εは小さすぎる可能性があります。浮動小数点数は内部的には精度のために一定の桁数しか格納できませんが、指数はそれよりも大きくなる可能性があります。その結果、浮動小数点誤差の原因、すなわち浮動小数点の最終桁は、単位桁よりも高い可能性があるどこかに現れる。言い換えれば、極端に大きな浮動小数点の場合、絶対誤差は1
よりも大きく、0.00001
のはるかに小さくなります。
小さな番号の場合:これはさらに明らかです。どちらの数字もイプシロンより小さい。たとえそれらを0と比較しても、相対誤差は無限大ですが、あなたはまだそれらが等しいと考えます。この場合、両方のオペランドを乗算するか、イプシロンを減らします。実際には同じですが、実装に関しては、小数(/ 0.0001
は* 10000
と等価)に掛け算されるオペランドの1つを除算するか、または大数の場合は除算すると便利です(/ 10000
差はおそらく10000
より小さくなります)
このチェックの別の名前があります。 abs($a - $b)
は絶対誤差と呼ばれますが、通常相対誤差を使用します。絶対誤差は÷近似値です。値も負の値になる可能性があるので、代わりにのabs
を全部返します。この場合の私たちの "イプシロン" 0.00001
は、私たちの許容相対誤差が0.00001
、すなわち0.001%誤差であることを意味します。
これは
であり、まだではありません。絶対に安全ではありません。あなたのプログラムで数多くの変換が行われた後は、数値をいくつかの大きな数値で追加/掛けた後、再び減算して、人間にとっては無視できる程度の大きな数値に不純な誤差を残します。したがって、イプシロン値または浮動小数点比較アルゴリズムを選択する前に、常に2度考えてください。
大きな数値を小さな数値で加算、減算、または乗算することは避けてください。エラーが発生する可能性が高くなります。あなたのアルゴリズムを開発する(特に単純化する)際には、常に浮動小数点にエラーがあるかもしれないことを考慮してください。これは仕事の負荷を馬鹿げた程度まで増加させるかもしれませんが、あなたがそれを認識している限り、このような心配は時々あなたがチームから追い出されるのを防ぎます。
@luweiqiない重複した、異なる質問。私は提案された複製をリンクさえしました。 – Twifty
あなたの更新された質問がより明確になりました。私は近い投票を退けました。乾杯! – Panda
関連:http://stackoverflow.com/q/328475/3990767 – SOFe