2013-05-02 64 views
1

在C++编程中,我什么时候需要担心精度问题?举一个小例子(它可能不是虽然是完美的一个),计算机精度:我应该什么时候担心它?

std::vector<double> first (50000, 0.0); 
std::vector<double> second (first); 

难道是可能的,second[619] = 0.000000000000000000000000000(我的意思是一个很小的值)。或者SUM = second[0]+second[1]+...+second[49999] => 1e-31?或SUM = second[0]-second[1]-...-second[49999] => -7.987654321e-12

我的问题:

  1. 难道是一些小的干扰与double型数字打交道?
  2. 什么可能导致这些小干扰?即舍入误差变大?你能列出他们吗?如何采取预防措施?
  3. 如果在某些操作中可能会有小的干扰,那么是否意味着在这些操作之后,使用if (SUM == 0)危险?那么应该总是使用if (SUM < SMALL)来替代,其中SMALL被定义为非常小的值,例如1E-30
  4. 最后,小干扰可能导致负值吗?因为如果可能的话,我应该更好地使用if (abs(SUM) < SMALL)来代替。

任何经验?

回答

4

这是浮点精度很好的参考文献:What Every Computer Scientist Should Know About Floating-Point Arithmetic

一个比较重要的部分是灾难性的取消时操作数都受到 舍入误差发生

灾难性取消。例如在二次公式中,出现表达式 b2-4ac。数量b2和4ac由于是浮点乘法的结果而受到四舍五入的 错误的影响。 假设它们四舍五入到最接近的浮点数 ,所以精确到0.5 ulp以内。当它们被扣除时, 取消可能导致许多准确的数字消失, 主要留下由舍入误差污染的数字。因此, 差异可能会有许多ulps的错误。例如,考虑b = 3.34,a = 1.22和c = 2.28。 b2 - 4ac的确切值是.0292。但b2轮到11.2和4ac轮到11.1,因此最终答案 是.1这是一个70 ulps的错误,尽管11.2 - 11.1正好是 等于.16。减法没有引入任何错误,而是暴露了早期乘法中引入的错误。

当减去确切的已知量时,会发生良性取消。 如果x和y没有舍入误差,那么通过定理2,如果用保卫位数完成相减,则差异x-y具有非常小的相对误差(小于2)。

显示灾难性取消的公式有时可以重新排列以消除该问题 。再次考虑二次 式

1
对于

您的具体实例中,0具有一个精确的表示为双,和精确地将0加至双不改变其值。

此外,和其他任何你放入变量的值一样,你在数组中初始化的数字也不会神秘地改变。当计算结果不能精确地表示为浮点数时,您只能取整。

为了给出关于“干扰”的更好的意见,我需要知道你的代码执行的计算种类。

相关问题