ユーザーが「設定された小数点数(有効数字)を使用して2つの浮動小数点数を比較する」ことを希望し、これは実際には関数があることを意味します
AlwaysEquals(14.3XXXXXXXX、14.3YYYYYYY、1)==すべての可能なXXXおよびYYYに対して真であり、最後のパラメーターは小数点以下の小数点以下の桁数です。
単純ですが残念な答えがあります:
この契約を履行するこの機能をプログラムすることはできません。多くの場合正しい結果が得られるものをプログラムすることは可能かもしれませんが、これがいつになるかを予測することはできないため、この関数は事実上無価値です。
ここで与えられた解は、AlmostEquals(0.06f、0.14f、1)= trueですが、0!=1ですでに壊れています。
なんで ?最初の理由は極端な感度です。例:0.0999999999....と0.100000... 1は、そもそも数字が異なりますが、違いはほとんど区別できず、ほぼ同じです。神話上の関数が何をするにしても、計算のわずかな違いさえ許すことはできません。
2つ目の理由は、実際に数値で計算したいということです。私はVC2008とC#を使用して、Math.pow関数の正しい値を出力しました。1つ目は精度パラメーター、2つ目は結果のfloatの16進値、3つ目は正確な10進値です。
1 3dcccccd 0.100000001490116119384765625
2 3c23d70a 0.00999999977648258209228515625
3 3a83126f 0.001000000047497451305389404296875
4 38d1b717 0.0000999999974737875163555145263671875
5 3727c5ac 0.00000999999974737875163555145263671875
6 358637bd 9.999999974752427078783512115478515625E-7
ご覧のとおり、シーケンス0.1、0.01、0.001などは、優れた近似値であるが、わずかに小さすぎるか大きすぎる数値を生成します。
指定された場所に正しい数字が必要であると強制した場合はどうなりますか?4ビットの16個のバイナリ値を列挙しましょう
0.0
0.0625
0.125
0.1875
0.25
0.3125
0.375
0.4375
0.5
0.5625
0.625
0.6875
0.75
0.8125
0.875
0.9375
小数点以下1桁だけで計算する場合は、10個の10進数に対して16個の異なる2進数で十分です。0.5はまったく同じですが、同じ10進数を適用すると、0.4には0.4375が必要であり、0.9には0.9375が必要であり、重大なエラーが発生します。
極端な感度の最初の条件に違反すると、そのような数値では合理的なことは何もできなくなります。数値の小数点以下の桁数に特定の値があることがわかっている場合は、最初に計算する必要はありません。
C#のドキュメントには、例も引用されています:http:
//msdn.microsoft.com/en-us/library/75ks3aby.aspx
発信者へのメモ
10進値を浮動小数点数として表すか、浮動小数点値に対して算術演算を実行すると精度が低下するため、場合によっては、Round(Double、Int32)メソッドが中間値を最も近い偶数に丸めないように見えることがあります。桁の小数点以下の値。これを次の例に示します。ここでは、2.135が2.14ではなく2.13に丸められています。これは、メソッドが内部で値を10桁で乗算するために発生し、この場合の乗算演算では精度が低下します。