C++ 当两个相等双精度的相对比较不';不行?

C++ 当两个相等双精度的相对比较不';不行?,c++,algorithm,floating-point,C++,Algorithm,Floating Point,我使用它描述的相对比较。 我有两双。第一个是计算结果: double d1(callComputation() ); 第二个定义如下: double d2(0.009); 我对近似相等的认识返回false,它是正确的,因为: std::printf("d1 = %25.20f\n", d1); 印刷品: d1 = 0.00900000000000011902 d2 = 0.00899999999999999932 及 印刷品: d1 = 0.0090000

我使用它描述的相对比较。 我有两双。第一个是计算结果:

double d1(callComputation() );
第二个定义如下:

double d2(0.009);
我对近似相等的认识返回false,它是正确的,因为:

      std::printf("d1 = %25.20f\n", d1);
印刷品:

d1 =    0.00900000000000011902
d2 =    0.00899999999999999932

印刷品:

d1 =    0.00900000000000011902
d2 =    0.00899999999999999932
我预计d2的代表将大致如下:

0.00900000000000011239 or 0.00900000000000000000 etc 
d1和d2的比较结果将为真。但是,即使是近似的Yequal也不能正常工作。在这种情况下,我应该如何比较? 我不需要高精度的计算,但显然我对
计算结果的稳定性。也许点后固定数量的数字(例如2)有助于解决此问题?

首先,这是最接近
.0009
的值,可以表示为双精度IEEE浮点数

每个浮点操作都可能导致舍入操作。基于Epsilon的策略不能可靠地确定两个浮点计算是否代表“相同”的实数

确定在一般情况下,两次计算是否导致或不导致同一实数实际上是不可数的;你可以减少它

确定它们是否相等的“最佳”最昂贵的通用方法是区间数学。用一对代表间隔的双打替换双打。在每次计算中,确保上双精度的结果向上舍入,下双精度的结果向下舍入(并且在除法/减法时,确保不翻转间隔,因为除法/减法是单调递减的;与负相乘相同)。如果将包含0的区间除以包含0的区间,请确保两个值均为NaN,如果将包含0的区间除以,则结果为+inf到-inf

区间数学有几个问题;这是昂贵的(明显超过2倍),需要用控制向上/向下舍入的操作替换每个基本操作,并且您会发现,经过大量的数学运算后,间隔会大得惊人

传统的IEEE舍入生成的值通常更接近您想要的值,因为它实际上随机舍入每个迭代。如果你掷硬币10000次,你会得到一个随机值,平均值5000,方差2500,标准偏差50;所以97%的时间你会在4900到5100之间,99%以上的时间你会在4850到5150之间。每个四舍五入操作实际上是一个加币+或-epusion/2(实际上更好;它加上一个+/-epsilon/2之间的值,被选为最小值),因此在10k操作后,可能的误差小于+/-75*epsilon。同时,区间数学将说明特定误差为+/-10000ε

TL;博士
你需要一个更大的ε。

这实际上非常困难,除非你告诉我们确切的呼叫上下文,否则可能无法回答。作为起点,连同你链接的问题一起阅读。正如那篇文章的作者所说,结果取决于
epsilon
。你没有给出你的epsilon,我们被认为是在猜测吗?我使用了机器epsilon:std::numeric\u limits::epsilon(),我是这个问题的新手,我认为机器epsilon是一个普遍的选择。现在我考虑如何选择给定精度的ε,因为没有通用的ε。据我所知,我需要一个函数来计算double所需的epsilon,比如:double epsilon(int numodigitsferfloatpoit)@mhd与名称的含义相反,
std::numeric\u limits::epsilon()
几乎从来都不是一个很好的值,可以用作绝对或相对比较的“epsilon”,如您链接的答案所示。理想情况下,您应该知道该值。如果您完全不知道,但必须使用某些东西,那么您链接到的答案中实现的相对比较的合理候选值是
std::numeric\u limits::epsilon()
,或简称
1.0e-8
。如何根据小数点后的位数选择epsilon的值?例如,对于点后的1、2、3位?@mhd,您需要选择相对于数字大小的ε-人为示例两个数字:1.00000000e20和1.00000001e20差为1.0e12,即仍然是一个大数字。