在constexpr: Introduction中,发言者提到“编译时浮点计算可能与运行时计算的结果不同”:
原因与“交叉编译”有关。
老实说,我不清楚。恕我直言,不同的平台也可能具有不同的整数实现。
为什么它只影响浮点数?还是我想念什么?
答案 0 :(得分:3)
在某种程度上,您绝对正确的是,在编译时计算浮点值的问题与计算整数值的问题相同。不同之处在于任务的复杂性。在具有16位寄存器的系统上模拟24位整数数学相当容易。对于认真的程序员来说,这是一个手指练习。如果没有本机实现,则进行浮点数学运算要困难得多。不需要浮点constexpr的决定部分是基于这种差异:要求交叉编译器在编译时为其目标平台模拟浮点数学确实非常昂贵。
另一个原因是可以在运行时设置浮点计算的某些详细信息。取整是一;处理上溢和下溢是另一回事。编译器根本无法了解浮点计算的运行时评估的完整上下文,因此无法可靠地在编译时计算结果。
答案 1 :(得分:2)
为什么只影响浮点数?
对于该标准,浮点运算精度没有限制。
根据expr.const,强调我的:
[注意:由于,本文档对以下内容的准确性不加任何限制: 浮点运算,是否未指定 翻译过程中的浮点表达式产生相同的结果 作为相同表达式(或相同运算符)的求值 相同的值)。 [示例:
bool f() { char array[1 + int(1 + 0.2 - 0.1 - 0.1)]; // Must be evaluated during translation int size = 1 + int(1 + 0.2 - 0.1 - 0.1); // May be evaluated at runtime return sizeof(array) == size; }
未指定
f()
的值是true
还是false
。 —示例]
—尾注]
答案 2 :(得分:1)
为什么只影响浮点数?
一些对整数的操作无效且未定义:
[编译器将在编译时间值上检测到这种情况。在运行时,行为不是标准定义的,可以是引发信号,模运算或“随机”行为的任何行为,如果编译器认为这些操作有效。]
有效整数上的运算在数学上已完全指定。
C / C ++(和大多数编程语言)中的整数除法是一个精确的运算,因为它是欧几里得除法,而不是试图找到有理除法的近似值的运算:5/3
是1,无穷十进制表示形式5/3的比例为1.66 ...或大约1.66666667;最接近的整数是2。
fp的目的是在“实数”(这四个操作实际上是有理数,根据定义浮点数是有理数)上提供数学运算的最佳近似。这些操作将根据当前舍入模式进行舍入,该模式使用std::fesetround
进行设置。因此,fp操作是取决于状态的,结果不仅是操作数的函数。 (请参见std::fegetround, std::fesetround。)
在编译时没有这种“状态”,因此根据定义,编译时fp操作不能与运行时操作一致。