浮点平等和容差

dor*_*ron 12 c c++ floating-point floating-accuracy

比较两个浮点数a_float == b_float由于寻找麻烦,因为a_float / 3.0 * 3.0可能不等于a_float由于舍入错误.

人们通常做的事情是这样的fabs(a_float - b_float) < tol.

如何计算tol

理想情况下,公差应该大于一个或两个最低有效数字的值.因此,如果使用单精度浮点数tol = 10E-6应该是正确的.然而,这对于a_float可能非常小或可能非常大的一般情况不适用.

如何tol正确计算所有一般情况?我特别感兴趣的是C或C++案例.

小智 17

这篇博文包含一个例子,相当简单的实现,以及它背后的详细理论 http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ 它也是一个系列之一,所以你可以随时阅读更多.简而言之:对于大多数数字使用ULP,对于接近零的数字使用epsilon,但仍有一些警告.如果你想确定你的浮点数学,我建议阅读整个系列.

  • 虽然确切的浮点比较*通常*寻找麻烦,但情况并非总是如此.有些时候,任何不完全比较的东西都是草率的,我在这里记录:https://randomascii.wordpress.com/2014/01/27/theres-only-four-billion-floatsso-test-them-all/这一切都取决于具体情况.换句话说,有时'tol'的正确值为零. (2认同)

unw*_*ind 9

据我所知,一个人没有.

没有一般的"正确答案",因为它可能取决于应用程序对精度的要求.

例如,在屏幕像素中工作的2D物理模拟可能决定1/4像素足够好,而用于设计核工厂内部的3D CAD系统可能不会.

我无法看到从外部以编程方式决定这一点的方法.

  • @urzeit我很确定`3e10000 - 100000`不是'2`,不管浮点错误. (2认同)

Chr*_*odd 5

C头文件<float.h>给你的常量FLT_EPSILONDBL_EPSILON,这是1.0和最小数大于1.0的浮标/双可以代表较大的区别.您可以根据数字的大小和您希望容忍的舍入误差来缩放:

#include <float.h>
#ifndef DBL_TRUE_MIN
/* DBL_TRUE_MIN is a common non-standard extension for the minimum denorm value
 * DBL_MIN is the minimum non-denorm value -- use that if TRUE_MIN is not defined */
#define DBL_TRUE_MIN DBL_MIN
#endif

/* return the difference between |x| and the next larger representable double */
double dbl_epsilon(double x) {
    int exp;
    if (frexp(x, &exp) == 0.0)
        return DBL_TRUE_MIN;
    return ldexp(DBL_EPSILON, exp-1);
}
Run Code Online (Sandbox Code Playgroud)