2016-09-13 2 views
1

У меня есть класс Java, который имеет дело с множеством тригонометрических функций, используя java.lang.Math. Следующий код определяет среднее направление 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 градусов приводит к очень маленькому, но положительному числу (из-за того, что работает точность с плавающей точкой). Если вы запустите вышеуказанный код, вы увидите, что я имею в виду. Как я могу избежать этого недостатка точности? Я знаю, что могу обойти средние синусы и косинусы, а также конечный результат, но для меня это кажется немного нелогичным.

+0

Математика с плавающей точкой подвержена ошибкам округления. Живи с этим. – Mick

+0

Я знаю, что это так. Я спрашиваю, как обойти это. – Kootling

+0

Что именно вы пытаетесь сделать? – Mick

ответ

0

Я считаю, что вы должны были рассмотреть углы усреднения напрямую (используя mod 360), прежде чем перейти к использованию sin/cos/tan. При этом, я думаю, вы находитесь в правильном направлении, чтобы получить то, что вы намеревались в своем коде (за исключением, возможно, отрицательного знака в последнем примере).

~> 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