在C ++中有效地乘以常数分数

时间:2014-03-27 13:12:03

标签: c++ performance

我正在实施Runge-Kutta程序,其中包括几个具有固定,复杂分数的时间关键乘法(这不是幻数但是算法固有的)我希望这种乘法尽可能高效地执行,同时保持代码可读。

为简单起见,假设我不需要关心效率,我们假设我的代码如下所示:

for (int i = 0; i < n; i++)
    a[i] += f(i) + b[i] * (2197/4104.);

我可以假设每个合理的编译器(带优化)都会有效地取代2197/4104 0.535331 ......?如果没有,有什么好方法可以确保这一点?例如,定义const double就足够了吗?

(请注意,我对优化上述代码的其他可能性不感兴趣 - 这只是一个例子。)

2 个答案:

答案 0 :(得分:4)

使用任何最新的编译器,评估将在编译时完成。

但是,如果您不能保证编译器会这样做,只需将计算提升出循环(如果可能,请设置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总和,最小精度损失。或者,尝试在求和时使用积分类型,然后执行除法作为最后一步。

答案 1 :(得分:0)

为了跳过浮点算术,你总是可以将你的数字乘以100000(我只是看了wiki上的Runge-Kutta,那是数字的位置)并对整数算法做整个算法。当你真正需要结果除以100000时。你使用2197/4104作为53533,你计算其他人(28561/56430 = 0.50435 - > 50435等等)。