C++ 比较C+中的双值+;

C++ 比较C+中的双值+;,c++,C++,我有以下代码用于双重比较。为什么我在执行时变得不平等 #include <iostream> #include <cmath> #include <limits> bool AreDoubleSame(double dFirstVal, double dSecondVal) { return std::fabs(dFirstVal - dSecondVal) < std::numeric_limits<double>::epsil

我有以下代码用于双重比较。为什么我在执行时变得不平等

#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;
}
}
#包括
#包括
#包括
布尔值是双重相同的(双重dFirstVal,双重dSecondVal)
{
返回std::fabs(dFirstVal-dSecondVal)

ε定义为“机器ε(1与可表示的大于1的最小值之间的差值)”-来源。这大约是
2.22045e-016
(来源)

如果要更改模糊因子,请与另一个小的双精度进行比较,例如:

bool AreDoubleSame(double dFirstVal, double dSecondVal)
{
    return std::fabs(dFirstVal - dSecondVal) < 1E-3;
}
bool是双重相同的(双重dFirstVal,双重dSecondVal)
{
返回标准::fabs(dFirstVal-dSecondVal)<1E-3;
}

两个双打的ε为
2.22045e-016

根据定义,ε是1和大于1的最小值之间的差值,即 可表示为数据类型

它们之间的差异大于此,因此返回false


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

epsilon比0.0003小得多,所以它们显然不相等

如果您想查看它的工作原理,请检查
epsilon()
仅是
1.0
1.0
之后可表示的下一个值之间的差值,即实际最小值。库函数
std::nextafter
可用于缩放任何量级数字的等精度测试

例如,使用
std::nextafter
测试
double
是否相等,方法是测试b是否都是比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;
}

当然,使用浮点运算时,需要对计算精度进行分析,以确定表示错误是如何形成的,从而确定正确的最小因子。

因为它们不相等?双精度的ε远比您想象的小。是什么让您相信它们应该相等?Print
Epsilon()
to stdout.@Als的可能重复不是重复,这里的数字明显不同。我们如何计算1E-3的值?这代表什么?它只是
0.001
的一个常量。它不是计算出来的或其他任何东西,它只是一个您选择的常量。1E-3是-3的指数幂的10,即0.001,或者,在其他wo中rds:1/1000。你能解释清楚为什么这比测试优越吗,abs(a-b)std::numeric_limits::epsilon()不能与大小不同于
1.0
的值一起使用。相反,
std::nextafter
可以用于获取任何大小的值的ε。因此,让我们声明..然后我将对您的答案进行投票。问题确实是浮点被视为定点并进行比较的趋势没有某种准确度分析。好吧,我试着编辑答案以便解释清楚,不幸的是,在同行评审之前,你无法阅读我的尝试
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;
}