Используя Java в Windows 7 PC (не уверенный, если это имеет значение) и называющий Math.cos () на значениях, которые должны возвратиться 0 (как пи/2) вместо этого, возвращает маленькие значения, но маленькие значения, что, если я не неправильно понимаю, намного больше, чем 1 ulp прочь от нуля.
Math.cos(Math.PI/2) = 6.123233995736766E-17
Math.ulp(Math.cos(Math.PI/2)) = 1.232595164407831E-32
Это на самом деле в 1 ulp, и я просто смущен? И это было бы приемлемым методом обертки для разрешения этой незначительной погрешности?
public static double cos(double a){
double temp = Math.abs(a % Math.PI);
if(temp == Math.PI/2)
return 0;
return Math.cos(a);
}
Не забывайте, что Math.PI / 2
является приблизительным. Это не будет точно pi / 2, поэтому результат cos (Math.PI / 2)
не будет точно 0. Math.cos
может возвращать довольно точную версию косинуса точного значения, полученного при вычислении Math.PI / 2
.
Никогда не используйте ==
с двойными числами. Вы всегда должны делать это в пределах погрешности. 10 -17 - хорошая точность, если вы спросите меня. Цифра Ulp 10 -32 - это просто точность двойного, то есть порядка 10 -17 , поскольку 2.220446049250313E-16 - это точность числа в 10 0 величина.
Это обычная ошибка, когда вы только начинаете, в этой ссылке есть очень техническое обсуждение причин, почему. {{1} } http://docs.sun.com/source/806-3568/ncg_goldberg.html
Но в простейшей форме, точно так же, как мы не можем точно представить 1/3 в десятичной системе. , есть значения, которые не могут быть представлены точно в двоичной системе