繁体   English   中英

为什么编译时浮点计算可能与运行时计算的结果不同?

[英]Why compile-time floating point calculations might not have the same results as run-time calculations?

constexpr:Introduction中 ,发言者提到“编译时浮点计算可能与运行时计算的结果不同”: 在此输入图像描述

原因与“交叉编译”有关。

老实说,我无法清楚地理解这个想法。 恕我直言,不同的平台也可能有不同的整数实现。

为什么它只影响浮点数? 或者我想念什么?

你是绝对正确的,在某种程度上,在编译时计算浮点值的问题与计算整数值的问题是一样的。 不同之处在于任务的复杂性。 在具有16位寄存器的系统上模拟24位整数数学是相当容易的。 对于认真的程序员来说,这是一个手指练习。 如果你没有本机实现,那么做浮点数学要困难得多。 不要求浮点constexpr的决定部分基于这种差异:要求交叉编译器在编译时为其目标平台模拟浮点数学将是非常昂贵的。

另一个因素是可以在运行时设置浮点计算的一些细节。 舍入是一个; 处理溢出和下溢是另一回事。 编译器根本无法知道浮点计算的运行时评估的完整上下文,因此无法可靠地在编译时计算结果。

为什么它只影响浮点数?

对于标准,不对浮点运算精度施加限制。

根据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 - 结束例子]
- 结束说明]

为什么它只影响浮点数?

对整数的一些操作无效且未定义:

  • 除以零:没有为操作数定义的数学运算
  • 溢出:给定类型无法表示的数学值

[编译器将在编译时值上检测此类情况。 在运行时,行为不是由标准定义的,可以是任何东西,例如,如果编译器假定操作有效,则抛出信号,模运算或“随机”行为。

对数组有效的整数的操作是完全以数学方式指定的

C / C ++(和大多数编程语言)中的整数除法是一个精确的操作,因为它是欧几里德除法,而不是试图找到有理数除法的近似逼近: 5/35/3 3的无限十进制表示是1.66 ...或约1.66666667; 最接近的整数是2。

fp的目的是提供关于“实数”的数学运算的最佳近似值(对于四个运算实际上是有理数,浮点数是合理的定义)。 根据使用std::fesetround设置的std::fesetround 舍入模式对这些操作进行舍 因此fp操作是依赖于状态的,结果不仅仅是操作数的函数。 (参见std :: fegetround,std :: fesetround 。)

在编译时没有这样的“状态”,因此根据定义,编译时fp操作不能与运行时操作一致。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM