Correct Way to Compare Floating-point Numbers
我正在计算N + fraction形式的实数值。比如说,N + fraction = 7.10987623,然后是N = 7和fraction = 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) |
号
- fabs(fraction - ratio)的结果没有说明fraction是大于还是小于ratio。当测试你认为正确的方法时,有五个相关的fraction值要测试:一个比ratio小得多,一个比ratio小得多,一个完全等于ratio(即使ratio不完全是23269/25920),一个比ratio大得多,一个比ratio大得多。一个ratio。如果你像那样测试你的两种方法,你会发现它们都不起作用。如果你写出这五个案例的预期结果,你就会找到答案。
- 投票决定重新开放,这个问题肯定有很多重复,但这里的重复是错误的。
- 比较fraction * 25920和23269怎么样?
- 您必须定义误差容限应该朝哪个方向发展。如果比率略大于23269/25920,您想做什么?如果稍微少一点,你想怎么办?
- @2501绝对不是复制品。这个问题是关于平等的问题,这个问题是关于订购平等的问题。它们看起来很相似,但实际上完全不同。
- 看起来你不明白大卫·施瓦茨在说什么。让我试着重新表述。数学比较告诉你两种情况中的哪一种发生了,(1) x < y或(2) x >= y。您有两个要执行的操作:do stuff when x < y和do other stuff when x >= y。这个决定很容易。机器浮点比较在正确执行时表示发生了三种情况中的哪一种:(1) x < y、(2) x > y和(3) x and y are too close to tell。您需要发明三个相应的操作,或者将两个案例放在一起。
- 为什么要使用Fabs?你知道n和你的比率都是正的吗?你想用epsilon做什么?你是不是想至少保证n>magic_比为epsilon?
- @早上好,你为什么不写个答案?
- @巴里,因为我认为在这种情况下,这样做是不对的。
你有正确的方法来比较平等:
1
| fabs(fraction - ratio) < EPSILON |
它在widthEPSILON的ratio周围建立了一个平等带。任何高于那个乐队的,都是绝对大的。因此,>检查是:
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可能不是fraction和25920.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都将产生相同的四舍五入:
。