cos градусов, не совпадающий с cos эквивалентных радианов

Все математические функции в JavaScript используют радианы вместо градусов. И все же они либо неравны, либо я далеко не в порядке.

Перевод из градусов в радианы:

var rad = angle * Math.PI / 180

Угол 90 градусов равен 1,57079633 радианам.

Косинус угла 90 градусов равен 0.
Косинус 1,57079633 радиана равно -3,20510345 × 10-9.

Обратите внимание, что в Javascript все делается за один шаг, чтобы избежать ошибок округления:

var cos = Math.cos(angle * Math.PI / 180);

Я, очевидно, упускаю здесь что-то очевидное, но, черт возьми, это портит код.


person SamGoody    schedule 19.09.2010    source источник


Ответы (6)


все делается в один шаг, чтобы избежать ошибок округления

Как это избежать ошибок округления? Это просто означает, что ошибки округления недоступны в отдельной переменной, вот и все.

Истинное значение числа пи не может быть точно представлено в виде числа с плавающей запятой, поэтому истинное значение числа пи / 2 тоже не может быть представлено. Таким образом, вы не можете дать Math.cos точное значение, необходимое для получения 0. Но ведь 10-9 — это очень, очень маленькое число. Это означает, что если бы вы рисовали линию длиной 10 000 километров, вы бы отклонились от соответствующей оси на 1 см.

Это именно то, чего следует ожидать при работе с числами с плавающей запятой. Не сравнивайте с равенством — сравнивайте в пределах некоторого допуска.

person Jon Skeet    schedule 19.09.2010
comment
218к!? Не обращал внимания, последний раз, когда я видел тебя, ты был на 10к! - person Rich Bradshaw; 19.09.2010
comment
Это мой первый вопрос, на который Джон Скит счел достойным ответа. - person SamGoody; 19.09.2010
comment
Допуск, о котором упоминал Джон, часто упоминается как эпсилон в официальных документах. - person Mr Bell; 17.07.2014
comment
@MrBell: Обычно я использую эпсилон для наименьшей представимой дельты (например, msdn.microsoft.com/en-us/library/system.double.epsilon.aspx), что не обязательно совпадает с допуском, который вы хотите выразить. Но это может быть только я. - person Jon Skeet; 18.07.2014

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

Измените свой код, чтобы он не «испортился», когда у вас есть ошибки порядка 1/1000000000.

person Matti Virkkunen    schedule 19.09.2010

Для большинства из нас, выполняющих серьезные вычисления на компьютерах, 0 IS равно -3,20510345×10^-9 с любой разумной степенью точности, которую вы имеете право ожидать при работе с числами с плавающей запятой. Это тема, которая регулярно освещается на SO.

person High Performance Mark    schedule 19.09.2010

Да, вы просто теряете данные о преобразованиях типов здесь.

90 градусов в радианах не равны точно 1,57079633. Если бы было больше десятичных знаков, это было бы преобразовано обратно, как и ожидалось.

С такими вещами всегда нужно быть осторожным. Как упоминалось выше, 10^-9 достаточно близко к нулю.

Также взято из MSDN:

Кроме того, результат арифметических операций и операций присваивания со значениями Double может немного отличаться в зависимости от платформы из-за потери точности типа Double. Например, результат присвоения буквального значения Double может отличаться в 32-разрядной и 64-разрядной версиях .NET Framework. В следующем примере показано это различие, когда литеральное значение -4,42330604244772E-305 и переменная со значением -4,42330604244772E-305 присваиваются переменной Double. Обратите внимание, что результат метода Parse(String) в этом случае не страдает от потери точности.

person iain    schedule 19.09.2010

В компьютерах π/2 радиана не может точно равняться 90 градусам, потому что π — бесконечно длинное число. Следовательно, нельзя ожидать идеальной точности с π, если только компьютер не является ∞-битным.

person Anonymous    schedule 07.03.2014

Я только что понял:

-3,20510345 × 10-9 равно -0,00000000320510345, что очень близко к нулю.

Преобразование Google в радианы округляется, и это округление вызывает ошибку.

Я предполагаю, что Javascript, который печально известен своей неточностью с числами, также создает неправильный радиан, и поэтому его кознак далеко.

Не уверен, как бы я это решил - округление неприемлемо, так как это не сработает для других углов.

person SamGoody    schedule 19.09.2010
comment
Я не думаю, что JS более известен отсутствием точности с числами, чем что-либо еще, использующее арифметику с плавающей запятой. Также было бы лучше, если бы вы добавили это как редактирование своего вопроса, а не публиковали его как ответ. - person Matti Virkkunen; 19.09.2010
comment
Когда я начал писать это как ответ, других ответов не было. И это действительно отвечает на вопрос - если бы я добавил его как правку, люди жаловались бы, что нет действительного вопроса. - person SamGoody; 19.09.2010