在纯c++中检测精度损失
detect the loss of precision in pure C++
当您使用浮点数(float
, double
, long 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++ 11或gnu++11特定的特性也被接受。
c++标准对浮点精度的概念非常模糊。没有完全符合标准的方法来检测精度损失。
GNU提供了一个扩展来启用浮点异常。您想要捕获的例外是FE_INEXACT
。
可以帮助您的是std::numeric_limits<double>::epsilon
,它返回"1与可表示的大于1的最小值之间的差值"。换句话说,它告诉您x
>0的最大值,使得1+x
的求值为1。
您可以考虑在boost库中使用间隔算法。它可以保证一个区间的误差在计算过程中总是递增的特性:∀ x ∈[a,b], f(x) ∈ f([a,b])
.
在您的示例中,您可以考虑将初始范围[a-EPS,a+EPS]
用于初始数字a
。经过一系列操作后,abs(y-x)
的结果区间[x,y]
将是您想要知道的(最大)精度损失。
您可以使用如下内容:
#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
相关文章:
- int 到浮点转换的精度损失
- 禁止具有精度损失的整数转换
- 添加双精度时精度损失
- ceil、floor 和 round 在转换为整数时会遇到精度损失问题吗?
- 精度损失
- 精度损失(分配)
- 在C++中使用 pow 时精度损失
- 从浮子到双精度,从双精度到浮子的精度损失
- 处理在减去两个彼此接近的双精度时的精度损失
- 精度损失
- 在C++中将双精度转换为字符串时精度损失
- 在C++中标记双精度损失的算法不会标记正确的位置
- 如果可以接受一些精度损失,如何快速紧凑地保存双精度矩阵
- 编译器不会警告精度损失
- 这种精度损失发生在哪里以及如何防止
- 添加双精度时精度损失
- 不投影和重投影的精度损失
- 计算幅度 <1 和幅度 >1 时的精度损失
- 从Int到Float到Int的转换精度损失
- 使用double时精度损失