Math.atan2的文档说



它说2 ulps的事实可能意味着在某些情况下返回的值不是最接近真实结果的double。有谁知道是否保证对相等的int参数对返回相同的值?换句话说,如果abk是正int值,并且a * kb * k都不会溢出,则可以确保

Math.atan2(a, b) == Math.atan2(a * k, b * k)

编辑

注意,对于非溢出的long乘法,绝对不是这种情况。例如
long a = 959786689;
long b = 363236985;
long k = 9675271;
System.out.println(Math.atan2(a, b));
System.out.println(Math.atan2(a * k, b * k));

版画
1.2089992287797169
1.208999228779717

但我找不到int值的示例。

最佳答案



简单地说,不。 Math文档是事实的来源,它不能保证您引用的2 ulp限制之外。这是设计使然(我们将在下面看到),因此任何其他来源都在暴露实现细节或完全错误。

尝试试探性地找到下界是不切实际的,因为 Math 的行为被证明是特定于平台的:



因此,即使您在测试中看到了更严格的界限,也没有理由相信这些界限可以跨平台,处理器或Java版本移植。

但是,正如Math的文档说明所述, StrictMath 具有更明确的行为。已记录StrictMath在各个平台上均能一致地执行,并且应具有与引用实现 fdlibm 相同的行为。该项目的 readme 注意:



您可以引用source code for atan2 并通过检查其实现来确定精确范围。 StrictMath.atan2()的任何其他实现都需要提供与引用实现相同的结果。

有趣的是,StrictMath.atan2()不包含与Math.atan2()相同的2 ulp注释。如果可以明确地重复fdlibm的“在一个ulp以下”注释会很好,但我认为缺少此注释意味着StrictMath的实现不需要包括该警告-它始终会低于一个ulp。

tl;博士如果需要精确结果或跨平台稳定结果,请使用StrictMathMath在精度与速度之间进行权衡。

关于java - 关于Math.atan2的保证,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37355486/

10-13 07:46