处理三角函数时的浮点精度

时间:2016-09-13 02:00:29

标签: java precision trigonometry

我有一个使用java.lang.Math处理大量三角函数的Java类。以下代码确定0度和180度的平均方向。结果应该是NaN,因为0度和180度是相反的方向,相互抵消。但是,当我这样做时:

double[] angles = {0, 180};
double sines = 0;
double cosines = 0;
double avg;
for (int i = 0; i < angles.length; i++) {
    double rad = Math.toRadians(angles[i]);
    sines += Math.sin(rad);
    cosines += Math.cos(rad);
}
double sin = sines / angles.length;
double cos = cosines / angles.length;
System.out.println("Avg sin: " + sin + "\nAvg cos: " + cos); // sin != 0 but it should
double avgRad = Math.atan2(sin, cos);
avg = Math.toDegrees(avgRad);
System.out.println("Average: " + avg);

avg等于90.0而不是NaN。这是因为180度和0度的平均正弦导致非常小但正数(由于浮点精度的工作方式)。如果您运行上面的代码,您将看到我的意思。我怎样才能避免这种缺乏精确性?我知道我可以围绕平均正弦和余弦以及最终结果,但这对我来说似乎有点不合适。

1 个答案:

答案 0 :(得分:0)

我认为你必须在使用sin / cos / tan之前直接考虑平均角度(使用mod 360)。话虽这么说,我认为,你在你的代码中得到你想要的东西是正确的方向(除了最后一个例子中可能的负号翻转)。

~> java Main 0 180
Avg sin: 6.123233995736766E-17
Avg cos: 0.0
Average: 90.0

~> java Main 0 179
Avg sin: 0.00872620321864172
Avg cos: 7.615242180436521E-5
Average: 89.50000000000011

~> java Main 1 179
Avg sin: 0.017452406437283477
Avg cos: 0.0
Average: 90.0

~> java Main 1 180
Avg sin: 0.008726203218641817
Avg cos: -7.615242180436521E-5
Average: 90.49999999999991

~> java Main 1 181
Avg sin: 1.5959455978986625E-16
Avg cos: 0.0
Average: 90.0

~> java Main 1 182
Avg sin: -0.008723545132608694
Avg cos: 2.2843406864775373E-4
Average: -88.50000000000001