关于c ++:比较浮点数的正确方法

Correct Way to Compare Floating-point Numbers

本问题已经有最佳答案,请猛点这里访问。

我正在计算N + fraction形式的实数值。比如说,N + fraction = 7.10987623,然后是N = 7fraction = 0.10987623,接下来,我需要检查fraction是否大于或等于23269/25920的比率。

下面,在C/C++中,似乎给出了正确的结果;然而,我不确定这是否是比较的正确方法:

1
2
3
4
// EPSILON is defined to be the error tolerance
// and `ratio' is defined as 23269.0/25920.0
if(fabs(fraction - ratio) > EPSILON)
 // `fraction' is greater or equal to `ratio'

我也试着用另一种方法,但结果似乎不正确。

1
if(fabs(fraction - ratio) < EPSILON)


你有正确的方法来比较平等:

1
fabs(fraction - ratio) < EPSILON

它在widthEPSILONratio周围建立了一个平等带。任何高于那个乐队的,都是绝对大的。因此,>检查是:

1
fraction > ratio + EPSILON

既然我们想要>=,我们就把这两个部分结合起来:

1
fraction > ratio - EPSILON

通过modf()把一个数分成整数和小数部分。如果有一个好的FP库,就不会有精度损失。

1
2
3
4
5
#include <math.h>
int foo(double N_plus_fraction) {
  double ipart;
  double fraction = modf(N_plus_fraction, &ipart);
  fraction = fabs(fraction);  // lets use the absolution fraction.

将阈值拆分为分子/分母部分并缩放分数。

1
2
3
  double f = fraction*25920.0;
  return f >= 23269.0;
}

由于产品f可能不是fraction25920.0的精确数学积,但最接近的四舍五入产品,因此代码可以使用f略大(或略小)的nextafter(),这取决于人们希望以何种方式对结果进行偏差。

1
2
3
4
  double f = fraction*25920.0;
  f = nextafter(f, 2*f);  // make f the next greater FP value.
  return f >= 23269.0;
}

预期的唯一不准确发生在fraction*25920.0步骤中。


不是指定一个EPSILON,它需要根据N的大小而变化,而是将N添加到ratio中,因为它和fraction都将产生相同的四舍五入:

1
x <= floor(x) + ratio