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 双打的 epsilon 是2.22045e-016

根据定义,epsilon 是 1 和大于 1 的最小值之间的差,该数据类型可表示。

这些差异不止于此,因此,它返回 false

参考

于 2012-09-05T09:42:12.337 回答
6

不相等(根据您的功能),因为它们相差超过epsilon.

Epsilon 被定义为“机器 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

如果你想改变 fucking 因子,比较另一个小的 double,例如:

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

你的两个双打之间的差异是 0.0003。std::numeric_limits::epsilon() 比这小得多。

于 2012-09-05T09:42:51.190 回答
5

epsilon()只是1.0和 之后可表示的下一个值之间的差1.0,即实际最小值。库函数std::nextafter可用于缩放任何数量级的数字的相等精度测试。

例如std::nextafter用于测试double相等性,通过测试 b 是否都是 <= 下一个小于 a 的数字 && >= 下一个大于 a 的数字:

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;
}

当然,这仅true适用于 a & b 的位模式相同的情况。因此,进行(不正确的)天真的直接 a == b 比较是一种低效的方法,因此:

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 回答
2

Epsilon 远小于 0.0003,因此它们显然不相等。

如果您想查看它的工作原理,请查看http://ideone.com/blcmB

于 2012-09-05T09:56:08.820 回答