Math.cos (Math.PI / 2) возвращает 6.123031769111886e-17 в JavaScript и AS3? - PullRequest
8 голосов
/ 08 ноября 2011

Если я правильно понимаю, JavaScript и ActionScript 3 работают с радианами.

Таким образом, ожидаемый результат следующих кодов будет:

Math.PI                 //Expected 3.141592653589793, got 3.141592653589793

Math.sin(0)             //Expected 0, got 0
Math.sin(Math.PI/2)     //Expected 1, got 1
Math.sin(Math.PI)       //Expected 0, got 1.2246063538223773e-16
Math.sin(Math.PI*3/2)   //Expected -1, got -1
Math.sin(Math.PI*2)     //Expected 0, got -2.4492127076447545e-16

Math.cos(0)             //Expected 1, got 1
Math.cos(Math.PI/2)     //Expected 0, got 6.123031769111886e-17
Math.cos(Math.PI)       //Expected -1, got -1
Math.cos(Math.PI*3/2)   //Expected 0, got -1.836909530733566e-16
Math.cos(Math.PI*2)     //Expected 1, got 1

Это то же самоеповедение в Firefox, Chrome, Safari, а также во Flash Professional CS5.5.Я использую Mac OS X 10.7.2.

Тест:

http://jsfiddle.net/KA4VM/

Ответы [ 5 ]

17 голосов
/ 08 ноября 2011

Вы смотрели на ценность, которую вы получаете?Вы ожидаете 0, но получаете что-то вроде

0.00000000000000012246063538223773

Разве это не достаточно близко к нулю для вас?

В принципе, вы не должны ожидать двоичных операций с плавающей запятойбыть точно правильным, когда ваши входные данные не могут быть выражены в виде точных двоичных значений - чего не может пи / 2, учитывая, что это нерационально.(Вы не должны ожидать, что результаты будут точными, даже если входные данные могут быть точно выражены в двоичном формате, если выходные данные не могут быть точно выражены ...)

2 голосов
/ 08 ноября 2011

Math.PI не является на 100% точным представлением числа пи, просто потому что число пи иррационально, а числа с плавающей запятой идут так далеко.

Таким образом, из-за ошибок округления вы получаете очень маленькие цифры (ваши цифры #. ##### e-16 и #. ##### e-17, которые крошечные).

Вы ничего не можете с этим поделать, кроме как признать, что 0,000000000000000006 достаточно близко к 0.

1 голос
/ 21 апреля 2017

Учтите, что все эти ошибки меньше 1e-15, что составляет около 2**(-50), поэтому мы можем добавить, а затем вычесть число с величиной 2**3, чтобы округлить результат. Поэтому, если мы выберем 8 в качестве числа, мы могли бы переопределить sin и cos следующим образом:

function sin(x) {
  return Math.sin(x) + 8 - 8;
}

function cos(x) {
  return Math.cos(x) + 8 - 8;
}

Это должно округлить ошибку, и это быстрее, чем toFixed метод.

1 голос
/ 01 февраля 2015

Поскольку PI - иррациональное число (Действительное число без Rational, невозможно вычислить с точным значением. Как сказал Джон Скит, тригонометрические методы объекта Math получают только приблизительные значения для PI и возвращают приблизительное значение. Если возвращение нулевых значений важно для вашего кода, вы должны округлить их. В таких случаях для удобства я расширяю эти объекты Javascript собственными методами:

Math.Sin = function(w){         
    return parseFloat(Math.sin(w).toFixed(10));
};

Теперь, пока вы получаете с

Math.sin(Math.PI)

этот странный результат

> 1.2246467991473532e-16

вы получаете то, что ожидали

Math.Sin(Math.PI)
> 0

Сделайте то же самое с другими тригонометрическими функциями:

Math.Cos = function(w){ 
    return parseFloat(Math.cos(w).toFixed(10));
};

и т. Д.

1 голос
/ 08 ноября 2011

Итак, у вас есть 1.xxxxx * 10 ^ -16

Это будет 0,0000000000000001xxx (пятнадцать нулей после десятичной точки)

Бьюсь об заклад, это достаточно близко к нулю, чтобы считать его 0.

Вы получаете эту бесконечно малую ошибку из-за ошибки в значении pi (как вы должны знать, после десятичной точки она растягивается до бесконечных цифр)

Вы не упомянули, получаете ли вы это в AS3 или JavaScript, хотя

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...