在Java中,我需要以独立于平台的方式计算
(int)Math.exp(x)
。为了实现平台独立性,我必须使用 StrictMath 来代替:(int)StrictMath.exp(x)
。不幸的是,我的测量表明 StrictMath.exp
明显慢于 Math.exp
。
因此,我有了先计算
y = Math.exp(x)
的想法。 Math.exp
的界面表明
计算结果与准确结果的误差必须在 1 ulp 以内。结果必须是半单调的。
所以,如果
(int)(Math.nextDown(y)) == (int)(Math.nextUp(y))
,我可以使用(int)y
作为结果。只有在极少数情况下(int)(StrictMath.nextDown(y)) != (int)(StrictMath.nextUp(y))
(结果预计在int
范围内),我才需要额外评估(int)StrictMath.exp(x)
。
如果
StrictMath.exp
具有与 Math.exp
相同的错误保证,则该策略将是正确的。
不幸的是,StrictMath.exp
界面中缺少相应的声明。 StrictMath 的 javadoc 只是说
为了帮助确保 Java 程序的可移植性,此包中的一些数值函数的定义要求它们产生与某些已发布算法相同的结果。这些算法可以从著名的网络库 netlib 中以“自由分发数学库”fdlibm 包的形式获得。这些用 C 编程语言编写的算法可以理解为按照 Java 浮点算术规则执行所有浮点运算。
Java 数学库是根据 fdlibm 版本 5.3 定义的。如果 fdlibm 为函数(例如 acos)提供多个定义,请使用“IEEE 754 核心函数”版本(位于名称以字母 e 开头的文件中)。需要 fdlibm 语义的方法有 sin、cos、tan、asin、acos、atan、exp、log、log10、cbrt、atan2、pow、sinh、cosh、tanh、hypot、expm1 和 log1p。
此外,fdlibm 库中的 exp 函数的接口说明了这一点
准确度:根据误差分析,误差始终小于1 ulp(最后一位单位)。
所有这些信息的组合是否真的意味着
StrictMath.exp
与 Math.exp
具有相同的错误保证?只有 100% 的保证才能让我进行上述优化。
所有这些信息的组合是否真的意味着
与StrictMath.exp
具有相同的错误保证?Math.exp
从表面上看1,错误保证是相同的;即小于 1 ulp。但这并不等于说错误是相同的!
使用
StrictMath
的目的并不是保证误差是可能的绝对最小值。相反,重点是保证“可重现”的结果,独立于编程语言、硬件实现等。
而另一面是,Math
方法(仍然是
2)没有指定产生与
StrictMath
等价物逐位相同的结果。正如 Java 17 中的javadoc所述:
“与
StrictMath
类的一些数字方法不同,类的等效函数的所有实现都未定义为返回逐位相同的结果。这种放宽允许性能更好的实现Math
在严格的情况下不需要重现性。”
相矛盾。Math
和
等价的内容。 我不认为它们保证是等价的:在任何版本的 Java 中都不保证。事实上,这会与上面的 javadoc 引用StrictMath
1 - 这是基于您在问题中引用的文字。
strictfp
语义(请参阅
JEP 306
),但这不会自动扩展到
Math
。