编译时常量与运行时常量

4

我目前正在开发自己的数学库,以提高我的C++技能。我偶然发现了boost常量头文件,我想知道使用编译时常量与运行时声明常量有什么区别?

const float root_two = 1.414213562373095048801688724209698078e+00;
const float root_two = std::sqrt( 2.0f );

在使用固定的编译时常量进行计算并在运行应用程序时使用函数时,是否会引入错误?如果使用运行时常量,那么这个错误就会被忽略吗?


3
运行时常量是什么?您是否指的是在运行时计算得出的值使用const访问? - πάντα ῥεῖ
2
它可以节省微瓦。将其乘以十亿台机器,就开始逐渐累积了 :) - Hans Passant
@HansPassant 到这一点,“过早的优化是万恶之源”。一般来说,如果你不是在编写将在成千上万个不同设置中使用(包括那些没有任何浮点硬件的设置)的头文件,则不必担心它。浮点值永远不能是constexpression,因此您不会获得任何提升。但是,const整数表达式可以用于指令(有时),因此您可以获得显着的性能提升。 - IdeaHat
编译器/ CPU 可能没有超级精确的平方根计算器(比如嵌入式系统等),这也是有可能的。如果您正在编写希望到处都能运行的代码,那么您不希望2的平方根(例如)出错。 - IdeaHat
1
@MadScienceDreams 这可以解释很多问题,但是还是有人在使用第二种方法吗? - Buni
我不确定你所说的“noone”是什么意思……很多人都知道。实际上,经验法则应该是“默认使用第三方提供的值(boost::constants)或自己的值,除非你正在编写嵌入式代码或计算该值太慢”。 - IdeaHat
2个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
2
  1. 正如HansPassant所说,这可能会为您节省微瓦。但请注意,编译器有时会通过在编译期间计算表达式并替换成字面值来优化代码。关于此问题,请参见我之前提出的问题的答案

  2. 使用固定的编译时常量是否会引入错误?如果您正在使用任意精度数据类型,则可能会。但是,使用像double这样的普通数据类型更有效,并且这些数据类型仅限于大约16个十进制数字的精度。

  3. 根据(2),您的第二个初始化不会比第一个更精确。实际上,如果您使用任意精度计算器预先计算了平方根的值,则字面值甚至可能会更加准确。


谢谢,我不知道第三种方法。但是,为什么我从来没有看到有人使用“运行时方法”呢?(它甚至更短)也许我还没有找对地方。 - Buni
1
@buni,你可能误解了3。我的意思是硬编码字面常量可能更精确。 - merlin2011

0
一个类似于Boost的库必须在大量环境中工作。使用该库的应用程序可能已经设置了FPU,处于flush-to-zero模式,导致非规范化(微小)结果为0.0。 或者应用程序可能已经编译了-fast-math标志,导致不准确的结果。 此外,(a + b + c) 的运行时计算取决于编译器生成的代码如何存储中间结果。它可能选择将(a + b)从FPU弹出,作为64位双精度浮点数,也可能将其保留在FPU堆栈上作为80位。这取决于许多因素,还包括结合律的代数重写。 总之,如果混合不同的处理器、操作系统、编译器以及库所用的不同应用程序,则每个上述排列的结果都不同。 在某些(罕见的)情况下,这是不希望的;您可能需要一个精确的常量值。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,