2

出于验证的目的,我希望能够计算出由于在某些特定算术计算期间舍入到可表示值而导致的累积误差的合理严格上限。

假设我们有一个foo()声称执行某些特定算术计算的函数。还假设存在关于最大误差(由于舍入)的隐含保证,该保证源于所涉及的类型是floatordouble以及执行计算的隐含(或陈述)方式foo()

我希望能够通过以foo()跟踪累积的最坏情况错误的方式执行计算来验证一组特定输入值的结果,然后检查两个结果是否与最终结果一样接近最坏情况下的错误要求。

我想可以通过引入一个新的算术类来做到这一点,该类track_prec<T>将精度跟踪添加到基本浮点类型之一,然后让该类的算术运算符的实现来计算最差的- 每个子表达式的大小写错误。我的问题是我不知道如何在这些一般情况下计算这些最坏情况错误:

// T = float or double
template<class T> class track_prec {
public:
    T value;
    T ulp; // http://en.wikipedia.org/wiki/Unit_in_the_last_place

    track_prec& operator+=(const track_prec& v)
    {
        value += v.value;
        ulp = ???; // How to do this? And what about -=, *=, and /=?
    }

    friend bool operator==(T, const track_prec&)
    {
        // Exactly how should this comparison be done?
    }
};

例如,假设这foo()是对一系列数字的简单求和。然后我们可以使用track_prec<T>如下:

std::vector<T> values { 0.4, -1.78, 1.3E4, -9.29E3, ... };
CHECK_EQUAL(std::accumulate(values.begin(), values.end(), track_prec<T>()),
            foo(values.begin(), values.end()));

当然,任何形式的帮助都是受欢迎的,但是指向免费和工作代码的指针会非常好。

我找到了有关该主题的这些链接,但它们似乎没有直接回答我的问题。

4

2 回答 2

3

跟踪浮点计算精度的最简单方法称为区间算术。它不需要 IEEE 754 算术,只是计算可以向上或向下舍入,以便每一步计算间隔的边界包含所有可能由相同计算产生的实数,如果它们是用实数完成的算术。

您应该能够找到许多现有的区间算术实现。

任何给定步骤的计算精度是在该步骤计算的间隔宽度。

注意常数:如果您希望近似 πx,您需要将包含 π 的浮点区间乘以 x 的区间。如果将 x 的区间乘以表示为 的双精度3.1415926535897932,您将得到 x 乘以该双精度的误差(既不等于 π 也不等于 3.1415926535897932)。在您问题的代码中,常量0.4表示“最接近 0.4 的双倍”。如果您需要有理数 4/10,请使用边界为分别由3.9999999999999997e-01和表示的两个双精度数的区间4.0000000000000002e-01

于 2013-10-06T15:15:18.680 回答
2

在此处查看错误跟踪是如何实现的。 https://github.com/Esri/geometry-api-java/blob/master/src/main/java/com/esri/core/geometry/ECoordinate.java

基本思想是浮点运算结果将接近正确值 +- 0.5 * DBL_EPSILON * 值。所以你可以跟踪和积累它。上面链接中的代码将计算 a + b 的绝对误差为

err(a+b) = err(a) + err(b) + DBL_EPSILON * abs(a + b). 

假设:IEEE 754 双精度浮点运算使用保护位。

于 2015-10-30T02:32:02.337 回答