1. ホーム
  2. c++

浮動小数点数とゼロを比較する

2023-11-15 03:13:42

質問

C++ FAQ lite "[29.17] 浮動小数点の比較がうまくいかないのですが? は、この等値性テストを推奨しています。

#include <cmath>  /* for std::abs(double) */

inline bool isEqual(double x, double y)
{
  const double epsilon = /* some small number such as 1e-5 */;
  return std::abs(x - y) <= epsilon * std::abs(x);
  // see Knuth section 4.2.2 pages 217-218
}

  1. これは、ゼロに等しい唯一の数は次のとおりであることを意味する、ということでよいでしょうか。 +0 であり -0 ?
  2. この関数はゼロをテストするときにも使うべきで、むしろ次のようなテストが必要です。 |x| < epsilon ?

更新

Daniel Daranas が指摘したように、この関数はおそらく isNearlyEqual と呼ぶべきでしょう (これは私が気にしているケースです)。

誰かが指摘した "Comparing Floating Point Numbers" を指摘されたので、もっと目立つように紹介したいと思います。

どのように解決するのですか?

あなたの観察は正しいです。

もし x == 0.0 であれば abs(x) * epsilon がゼロであるかどうかをテストしているのです。 abs(y) <= 0.0 .

もし y == 0.0 であれば、テストしているのは abs(x) <= abs(x) * epsilon のどちらかをテストしていることになります。 epsilon >= 1 (これは違う) または x == 0.0 .

ということで、どちらかというと is_equal(val, 0.0) または is_equal(0.0, val) は無意味であり、単に val == 0.0 . もし まさに +0.0 そして -0.0 .

この場合、FAQの推奨は限定的な有用性しかありません。

浮動小数点の比較には、1 つのサイズですべてに対応するものはありません。 変数のセマンティクス、許容される値の範囲、そして計算によってもたらされる誤差の大きさについて考えなければなりません。 FAQ でも注意事項があり、この関数は通常 x と y の大きさがイプシロンよりかなり大きい場合は問題ないと言っていますが、あなたの判断は異なるかもしれません" 。