2014-02-12 3 views
0

Клиент настаивает на том, что sin (Math.PI) и cos (Math.PI/2) должны возвращать ноль, а не что-то около 10^-16. Он недоволен объяснением того, что Math.sin() и Math.cos() являются такими, какими они есть, не только в Javascript, но и на всех других языках.Действующее решение для Javascript sin() и cos()?

Одно я нашел, что Math.sin() нечувствителен к параметру изменяется меньше, чем 2й-16:

Math.sin(Math.PI) 
1.2246063538223773e-16 
Math.sin(Math.PI + 1e-16) 
1.2246063538223773e-16 
Math.sin(Math.PI + 2e-16) 
1.2246063538223773e-16 
Math.sin(Math.PI + 3e-16) 
-3.216285744678249e-16 

Так как Sin (х) = х ~ когда грех (х) близки к нулю , мне приходилось бросать sin (x) в ноль, когда x меньше, чем 2e-16.

Math.cos() является более точным, он нечувствителен к изменениям до 1.1e16 (EDIT: это происходит потому, что базовое значение меньше: Math.PI/2) поэтому я бы отливать сова (х) равно нулю, когда он меньше, чем 1е-16:

Math.cos(Math.PI/2) 
6.123031769111886e-17 
Math.cos(Math.PI/2 + 1e-16) 
6.123031769111886e-17 
Math.cos(Math.PI/2 + 1.1e-16) 
6.123031769111886e-17 
Math.cos(Math.PI/2 + 1.5e-16) 
-1.6081428723391245e-16 

конечно, такой бросок будет разрушить первоначальную хорошую точность греха (х) при х> 0:

Math.sin(1e-99) 
1e-99 
Math.sin(1e-50) 
1e-50 
Math.sin(1e-40) 
1e-40 
Math.sin(1e-20) 
1e-20 
Math.sin(1e-10) 
1e-10 
Math.sin(1e-5) 
0.000009999999999833334 

Но если приложение использовало такие малые углы, оно должно использовать x напрямую, а не sin (x), правильно? Так как sin (x) в этом диапазоне полностью стремится к х.

Учитывая, что приложение имеет 10 цифр точности UI, чувствуете ли вы, что моя стратегия правильная?

+7

«* Клиент настаивает *» получить лучшие клиент, предпочтительно те, которые имеют некоторое представление о точке математики с плавающей запятой. Клиент также требует, чтобы '.1 + .2 == .3'? –

+0

«Так как sin (x) ~ = x, когда sin (x) близок к нулю» - неправильно. Это - когда x близок к нулю. – Igor

+0

@epx Посмотрите, есть ли http://mathjs.org/ любой помощи –

ответ

2

Вы можете принять решение о том, как близко к нулю, вы хотите вернуть нулевую

Number.prototype.rounded= function(i){ 
    i= Math.pow(10, i || 15); 
    // default 
    return Math.round(this*i)/i; 
} 
Math.sin(Math.PI).rounded() 
/* returned value: (Number) 0 */ 

Math.PI.rounded(5) 
/* returned value: (Number) 3.14159 */ 
+1

+1, компьютеры, работающие с ** номерами **, как 'π', могут только ** приближаться **, то есть' Math.PI' не равно 'π', поэтому' sin (Math.PI) 'уже отличается от 'sin (π)'. Этот ответ позволяет вам лучше понять, насколько велика ваша компьютерная ошибка в ваших расчетах. Если клиент хочет, чтобы решения выполнялись символически, вы можете реально использовать идентификаторы и, возможно, избегать целочисленного сложения, вычитания и умножения. –

Смежные вопросы