【问题标题】:Java Math.cos(Math.toRadians(<angle>)) returns weird valuesJava Math.cos(Math.toRadians(<angle>)) 返回奇怪的值
【发布时间】:2012-10-27 12:23:11
【问题描述】:

Math.cos() 方法有点问题。我知道,在使用Math.cos() 之前,我必须将角度转换为弧度。但如果我这样做:

System.out.println(Math.cos(Math.toRadians(90));

输出:6.123233995736766E-17

Math.sin() 运行良好。

【问题讨论】:

标签: java math angle trigonometry


【解决方案1】:

从三角函数:

sin x ~= x, for small values of x
sin x = cos x+pi/2

由于 pi/2 不能在 IEEE-754 浮点中精确表示,这意味着它必须由某个值 x 关闭,即它由 pi/2 +- x 表示,其中 x

在这种特殊情况下,x ~= 6.123233995736766E-17,大约是最大误差的 55%。 所以,这是一个相当不错的结果......

【讨论】:

    【解决方案2】:

    请参阅 Javadoc。 “从度数到弧度的转换通常是不精确的。”

    【讨论】:

    • cos x-pi/2 = sin x ~= x 值较小,不幸的是 90/180*pi - 与 pi/2 的实际值相差这么多。
    【解决方案3】:

    该值非常接近正确结果。将度数转换为弧度的浮点运算似乎损失了精度。

    【讨论】:

    • 这是预期的 IEEE 574 浮点行为,我不会称其为“问题”。请参阅 Esailija 的评论。
    • @ignis Math.cos() 的值必须在正确结果的 1ulp 以内。没有多少戈德堡可以解释这一点。
    • 虽然我没有否决您的回答,但我认为否决票来自您的陈述方式。通过暗示这是一个“问题”,即精度损失,而不是使用浮点运算的预期结果,你会混淆事情。
    • 好的,这不是问题,我删除了这个词并稍微解释了一下。
    【解决方案4】:

    暂时站在肥皂盒上,我想人们对accuracy versus precision 的概念感到困惑。这是否像某些人所说的那样是一个问题?这是个问题吗?一个错误?还是浮点运算的预期行为?

    90 度是一个可以完美表示为整数的数字,即使是双精度数。但是 pi/2 弧度是一个没有精确表示的实数,因此表示会稍微不准确。损失在于准确性。事实是,这是预期的行为。我们永远不应该相信结果的最低有效位。

    接下来,当我们计算三角函数的值时,可能会有额外的精度损失。我们并没有得到我们知道在象征意义上是真实的结果。因此 sin(pi/3) 可能不完全是 sqrt(3)/2,但无论如何我们不能完全表示 sqrt(3)/2。所有这些都是意料之中的,并且是应该由好的代码处理的行为,而不是信任这些数字的 LSB。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-10-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-12
      相关资源
      最近更新 更多