我正在实现一个 Runge–Kutta 程序,其中包括几个时间关键的乘法与固定的、复杂的分数(这不是魔数(Magic Number),而是算法固有的),我希望这种乘法尽可能高效地执行,同时保持代码可读。
为了简单起见,假设我的代码如下所示,如果我不需要关心效率的话:
for (int i = 0; i < n; i++)
a[i] += f(i) + b[i] * (2197/4104.);
我可以假设每个合理的编译器(经过优化)都能有效地将 2197/4104 替换为 0.535331 吗……?如果没有,确保这一点的好方法是什么?例如,定义一个 const double
就足够了吗?
(请注意,我对优化上述代码的其他可能性不感兴趣——这实际上只是一个示例。)
最佳答案
使用任何最新的编译器,评估将在编译时完成。
但是,如果您不能保证编译器会这样做,只需将计算从循环中取出(如果可能,制作一个 const long double
):
long double fraction = (2197/4104.);
for (int i = 0; i < n; i++)
a[i] += f(i) + b[i] * fraction;
如果求和的准确性很重要并且 f(i)
或 b[i]
的大小可能很大(我假设可能很大),那么您最好不要使用 +=
对值求和,而是查看 Kahan summation algorithm总而言之,精度损失最小。或者,尝试在求和时使用整数类型,然后在最后一步执行除法。
关于c++ - 在 C++ 中有效地乘以常数分数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22688733/