【问题标题】:Custom math functions vs. supplied Math functions?自定义数学函数与提供的数学函数?
【发布时间】:2015-03-14 11:50:27
【问题描述】:

我基本上是在制作一个必须非常快速地运行大量计算的 Java 程序(每帧,目标至少为 30 f/s)。这些将主要是三角函数和幂函数。 我要问的问题是: 哪个更快:使用 Java Math 已经提供的函数?还是编写我自己的函数来运行?

【问题讨论】:

  • 客观的答案是,这取决于你能做多好,等等。
  • 作为一般经验法则 - 为一种语言提供的数学函数库总是比您提供的更快,因为它们可以选择以不可用的方式进行优化给你(除非你用汇编程序编写你的)。
  • 即使java.lang.Math没有你需要的功能,但肯定有人解决了同样的问题,写了library to solve it。事实上,not invented here(NIH Syndrome)是软件开发中众所周知的反模式,与reinventing the wheel密切相关。

标签: java math calculator trigonometry exponent


【解决方案1】:

内置的Math 函数将很难被击败,因为它们中的大多数都具有特殊的 JVM 魔法,使它们能够使用硬件内在函数。您可以可以想象通过大量工作来牺牲准确性来击败其中的一些,但您不太可能击败Math其他实用程序。

【讨论】:

  • 虽然我同意一般评估,但创建自定义函数实现可能不一定需要大量工作,具体取决于程序员的技能和对函数的限制。较低的准确性只是一种可能的权衡,其他人仅支持有限的参数范围[在三角函数的情况下特别有用]并且不必处理特殊情况[对pow()非常有用,这会产生很多特殊例]。
【解决方案2】:

您将需要使用 java.lang.Math 函数,因为它们中的大多数在 JVM 中运行 native。可以看源码here

【讨论】:

  • 即使不是本机的方法也可能是内在的,即 Java 代码永远不会运行,而是在运行时被 JVM 替换为更高效的代码。
【解决方案3】:

多年来,许多非常聪明和合格的人付出了很多努力,以使数学函数尽可能快速和准确地工作。因此,除非你比所有人都聪明,并且有多年的空闲时间花在这上面,否则你不太可能做得更好。

它们中的大多数也是原生的——它们实际上并不是在 Java 中。因此,用 Java 编写它们的更快版本将是完全不行的。当您开始编写自己的语言时,您可能最好混合使用 C 和汇编语言;而且您需要知道要在其上运行的任何硬件的所有怪癖。

此外,当前的实现已经过多年测试,因为全世界有数百万人以某种方式使用 Java。您将无法访问同一组测试人员,因此您的函数将自动比标准函数更容易出错。这是不可避免的。

那么你还在考虑编写自己的函数吗?

【讨论】:

    【解决方案4】:

    缓存值可能是一种选择。如果您知道您只需要一组固定的值,或者如果您可以在没有完美准确性的情况下逃脱,那么这可以节省大量时间。假设你想画很多圆圈,预先计算每个度数的 sin 和 cos 值。然后在绘图时使用这些值。大多数圆圈足够小,以至于您看不到差异,并且可以使用库来完成非常大的小数字。

    请务必测试这是否值得。在我 5 岁的 macbook 上,我每秒可以进行 100 万次 cos 评估。

    【讨论】:

      【解决方案5】:

      如果你能承受 1e-15ish 的相对误差(或者更像是 pow(double,double) 的 1e-13ish),你可以试试这个,如果你经常调用它,它应该比 java.lang.Math 更快: http://sourceforge.net/projects/jafama/

      正如某些人所说,如果您想保持相似的 (1-ulp-ish) 精度,通常很难在纯 Java 中击败 java.lang.Math,但双精度精度稍差通常是完全可以忍受的(并且仍然比使用浮点数计算时要准确得多),并且可以显着加快速度。

      【讨论】: