我最近遇到了一个问题:
我不得不在一个程序中做一些复杂的数学运算。一位朋友注意到它运行缓慢并告诉我,通过公式中的一些简单重新排列可以改善结果的计算。像这样:
1/15 * x = x/15
or
2*x + 2*y = 2*(x + y)
我知道这些都很简单。所以我有一个更复杂的例子:
我的CAS给了我这个公式:
-1/10*v+1/15*(3*v^2+60*s)^(1/2)
我把它放在Java中:
(Math.sqrt(3.0 * (v*v + 20.0*s))/15.0) - (v/10.0)
这是一个巨大的进步。但我很确定这可以通过其他一些简单的优化进一步优化
我提出了一些其他等效的公式。但是,我怎么知道哪个是最快的(当然没有剖析。每个人都可以这样做而且需要花费很多时间)。
(显然最后一个是最快的。)
((2.0 * Math.sqrt(3.0 * (v*v + 20.0*s))) - (3.0 * v))/30.0
((3.4641016151377544 * Math.sqrt(v*v + 20.0*s)) - (3.0 * v))/30.0
((3.4641016151377544 * Math.sqrt(v*v + 20.0*s)) - (3.0 * v)) * 0.03333333333333333
(Math.sqrt(v*v + 20.0*s) - (0.8660254037844387 * v)) * 0.11547005383792515
我真的把上面的公式带到了极限(重新排列公式以摆脱不必要的操作并预先计算一些常量......真的不容易!)。这一切都是通过手工和一些数学知识完成的。另外,老实说,我怀疑任何编译器或解释器(Java和其他运行时解释语言)都能够将(Math.sqrt(3.0 * (v*v + 20.0*s))/15.0) - (v/10.0)
转换为更快的公式(Math.sqrt(v*v + 20.0*s) - (0.8660254037844387 * v)) * 0.11547005383792515
,这将得到完全相同的结果......
这是一项耗费大量时间的大量工作。特别是如果有几个公式的数量
事实上,你可以对一个公式做一些小改动,其中一些可以真正帮助提高计算速度。
是否有类似于为C / C ++ / Java代码优化此类公式的工具?
(如果需要更多示例,我会提供更多)
(假设所有计算中都有浮点运算。我只是想让公式保持简单易读)
答案 0 :(得分:3)
有一本名为Numerical Recipes的经典书籍。
数学方程式的效率可能不是实现最简单的形式。
示例:z = 2 * x + 2 * y;
如上所述,有两个乘法运算和一个加法运算。
使用分配属性,可以改写为:
z = 2 *(x + y);
现在只有一个乘法运算。
一般来说,操作按照从最快到最慢的顺序排列如下:
其他技术包括循环展开(在重新启动循环之前执行许多语句)和数据设置(在处理之前加载所有数据)。