std::pair<double,double> TwoSum(double a,double b) { double s = a + b; double v = s - a; double e = (a - (s - v)) + (b - v); return std::make_pair(s,e); }
误差的计算e依赖于以下事实:由于IEEE-754浮点数学的非关联属性,计算遵循该操作顺序.
如果我在现代优化C编译器(例如MSVC或gcc)中编译它,我是否可以确保编译器不会优化计算的方式?
其次,这是否在C标准的任何地方得到保证?
解决方法
第1.9节程序执行(C 0x N3092)状态:
Operators can be regrouped according to the usual mathematical rules only where the operators really are associative or commutative.
在分组方面,5.1主要表达式指出:
A parenthesized expression is a primary expression whose type and value are identical to those of the enclosed expression. … The parenthesized expression can be used in exactly the same contexts as those where the enclosed expression can be used,and with the same meaning,except as otherwise indicated.
我相信在该引用中使用“相同”一词需要符合要求的实施,以保证它将以指定的顺序执行,除非另一个订单可以给出完全相同的结果.
对于加法和减法,第5.7节“附加运算符”具有:
The additive operators + and – group left-to-right.
所以标准决定了结果.如果编译器可以确定可以通过不同的操作顺序获得相同的结果,那么它可以重新排列它们.但无论这种情况发生与否,您都无法辨别出差异.