2

二重比較のために次のコードがあります。実行時に等しくないのはなぜですか?

#include <iostream>
#include <cmath>
#include <limits> 

bool AreDoubleSame(double dFirstVal, double dSecondVal)
{
    return std::fabs(dFirstVal - dSecondVal) < std::numeric_limits<double>::epsilon();
}


int main()
{
double dFirstDouble = 11.304;
double dSecondDouble = 11.3043;

if(AreDoubleSame(dFirstDouble , dSecondDouble ) )
{
std::cout << "equal" << std::endl;
}
else
{
std::cout << "not equal" << std::endl;
}
}
4

5 に答える 5

17

2 double のイプシロンは2.22045e-016

定義によると、イプシロンは、1 と、データ型で表現可能な 1 より大きい最小値との差です。

これらはそれ以上に異なるため、 false を返します

参考

于 2012-09-05T09:42:12.337 に答える
6

は (関数によると) 等しくありませんepsilon

イプシロンは、「マシン イプシロン (表現可能な 1 と 1 より大きい最小値との差) 」として定義されます- ソースhttp://www.cplusplus.com/reference/std/limits/numeric_limits/ これはおよそです2.22045e-016(ソースhttp://msdn.microsoft.com/en-us/library/6x7575x3(v=vs.71).aspx )

ファッジ係数を変更する場合は、別の小さな double と比較します。たとえば、次のようになります。

bool AreDoubleSame(double dFirstVal, double dSecondVal)
{
    return std::fabs(dFirstVal - dSecondVal) < 1E-3;
}
于 2012-09-05T09:41:23.493 に答える
5

epsilon()1.0は、と の後に表現可能な次の値1.0、実際の最小値との差のみです。ライブラリ関数std::nextafterを使用して、任意の大きさの数値の等値精度テストをスケーリングできます。

たとえば、b が <= a よりも次の数が小さい && >= a よりも次の数が大きいことをテストすることにより、等しいかどうかstd::nextafterをテストするために使用します。double

bool nearly_equal(double a, double b)
{
  return std::nextafter(a, std::numeric_limits<double>::lowest()) <= b
    && std::nextafter(a, std::numeric_limits<double>::max()) >= b;
}

もちろん、これはtruea と b のビット パターンが同じ場合のみです。したがって、(間違った) 素朴な直接 a == b 比較を行う非効率的な方法です。したがって、次のようになります。

表現可能な差にスケーリングされたいくつかの要因内で2つが等しいかどうかをテストdoubleするには、次を使用できます。

bool nearly_equal(double a, double b, int factor /* a factor of epsilon */)
{
  double min_a = a - (a - std::nextafter(a, std::numeric_limits<double>::lowest())) * factor;
  double max_a = a + (std::nextafter(a, std::numeric_limits<double>::max()) - a) * factor;

  return min_a <= b && max_a >= b;
}

もちろん、浮動小数点を扱う場合は、表現誤差がどのように蓄積されるかを判断し、正しい最小係数を決定するために、計算精度の分析が必要になります。

于 2016-02-07T11:39:29.867 に答える
5

2 つの double の差は 0.0003 です。std::numeric_limits::epsilon() はそれよりもはるかに小さいです。

于 2012-09-05T09:42:51.190 に答える
2

Epsilon は 0.0003 よりもはるかに小さいため、明らかに等しくありません。

どこで機能するかを確認したい場合は、http://ideone.com/blcmBを確認してください。

于 2012-09-05T09:56:08.820 に答える