在C ++编程中,何时需要担心精度问题?举一个小例子(尽管可能不是一个完美的例子),
std::vector<double> first (50000, 0.0);
std::vector<double> second (first);
有可能是second[619] = 0.00000000000000000000000000001234
(我的意思是一个非常小的值)。还是SUM = second[0]+second[1]+...+second[49999] => 1e-31
?或SUM = second[0]-second[1]-...-second[49999] => -7.987654321e-12
?
我的问题:
double
类型号码时可能会出现一些小干扰吗?if (SUM == 0)
是危险?然后应该总是使用if (SUM < SMALL)
,而SMALL
被定义为非常小的值,例如1E-30
?if (abs(SUM) < SMALL)
。有经验吗?
答案 0 :(得分: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 :(得分:1)
对于您的具体示例,0具有精确表示为double,并且将0精确地添加到double不会更改其值。
此外,与放入变量的任何其他值一样,在数组中初始化的数字也不会神秘地改变。只有当计算结果无法准确表示为浮点数时,才会进行舍入。
为了更好地了解“干扰”,我需要知道代码执行的计算类型。