我正在实施Runge-Kutta程序,其中包括几个具有固定,复杂分数的时间关键乘法(这不是幻数但是算法固有的)我希望这种乘法尽可能高效地执行,同时保持代码可读。
为简单起见,假设我不需要关心效率,我们假设我的代码如下所示:
for (int i = 0; i < n; i++)
a[i] += f(i) + b[i] * (2197/4104.);
我可以假设每个合理的编译器(带优化)都会有效地取代2197/4104 0.535331 ......?如果没有,有什么好方法可以确保这一点?例如,定义const double
就足够了吗?
(请注意,我对优化上述代码的其他可能性不感兴趣 - 这只是一个例子。)
答案 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等等)。