4

当您使用浮点数(类型)进行操作时,是否可以检测到精度损失float?说:doublelong double

template< typename F >
F const sum(F const & a, F const & b)
{
    F const sum_(a + b);
    // The loss of precision must be detected (here or one line above) if some fraction bit is lost due to rounding
    return sum_;
}

x87 FPU 存在于目标架构上时尤其感兴趣,但没有asm例程干预到纯 C++ 代码中。如果有的话,也接受C++11gnu++11的特定功能。

4

4 回答 4

4

C++ 标准对浮点精度的概念非常模糊。没有完全符合标准的方法来检测精度损失。

GNU提供了一个扩展来启用浮点异常。您要捕获的异常是FE_INEXACT.

于 2013-01-19T21:02:55.943 回答
1

您可以考虑在 boost 库中使用区间算法。它可以保证在计算过程中一个区间的误差总是增加的性质:∀ x ∈[a,b], f(x) ∈ f([a,b]).

在您的情况下,您可能会考虑使用初始范围[a-EPS,a+EPS]作为初始数字a。经过一系列操作,abs(y-x)结果间隔[x,y]将是您想知道的(最大)精度损失。

于 2013-01-19T21:18:40.213 回答
1

对您有帮助的一件事是std::numeric_limits<double>::epsilon,它返回“1 与可表示的大于 1 的最小值之间的差”。换句话说,它告诉您最大的x>0 使得1+x计算结果为 1。

于 2013-01-19T21:11:44.170 回答
1

您可以使用以下内容:

#include <iostream>
#include <fenv.h>

#pragma STDC FENV_ACCESS ON

template <typename F> F sum (const F a, const F b, F &error) {
    int round = fegetround();

    fesetround(FE_TONEAREST);
    F c = a + b;

    fesetround(FE_DOWNWARD);
    F c_lo = a + b;

    fesetround(FE_UPWARD);
    F c_hi = a + b;

    fesetround(FE_TONEAREST);
    error = std::max((c - c_lo), (c_hi - c));

    fesetround(round);

    return c;
}


int main() {
    float a = 23.23528;
    float b = 4.234;
    float e;

    std::cout << sum(a, b, e) << std::endl;
    std::cout << e << std::endl;
}

error参数中返回对最大错误量的快速估计。请记住,切换舍入模式会刷新浮点单元 (FPU) 流水线,因此不要指望超快的速度。

更好的解决方案是尝试区间算术(倾向于给出悲观的误差区间,因为没有考虑变量相关性)或仿射算术(跟踪变量相关性,因此给出了更严格的误差范围)。

在这里阅读这些方法的入门: http ://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.36.8089

于 2016-03-16T18:44:15.633 回答