2015-03-09 6 views
1

Я столкнулся с чем-то весьма интересным, пока я играю с модулем math для тригонометрических вычислений с использованием , sin и cos.Триггерные функции Python не возвращают согласованные результаты

Как сказано это все математические учебники, источник онлайн, и курсы, верно следующее:

tan(x) = sin(x)/cos(x)

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

from math import tan, sin, cos 

theta = -30 
alpha = tan(theta) 
omega = sin(theta)/cos(theta) 

print(alpha, omega) 
print(alpha == omega) 

>>> (6.405331196646276, 6.4053311966462765) 
>>> (False) 

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

Есть ли что-то, что мне не хватает?

+0

[Что каждый программист должен знать о арифметике с плавающей точкой] (http://floating-point-gui.de/) – MattDMo

+0

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

ответ

3

Эта проблема связана с конечной точностью с плавающей точкой (не все реальные числа могут быть представлены точно, а не все вычисления с ними точны). Доступный справочник находится в Python docs.

Использование представления с плавающей запятой по принципу «двойная точность», вы никогда не сможете надеяться на точность, превышающую точность в 15 знаков после запятой, и вычисления с использованием таких чисел будут иметь тенденцию ухудшать эту точность (ошибка округления, упомянутая в приведенном выше комментарии) , Таким же образом, вы получаете False из следующих функций:

In [1]: 0.01 == (0.1)**2 
Out[1]: False 

потому, что Python не квадратуры 0.1, но «ближайшего представимого число» до 0,1, который не является ни 0,01, ни ближайшим представляемым числом 0,01.

D Стэнли дал правильный способ проверить «равенство» в пределах абсолютного допуска: (abs(a-b) < tol), где tol - это небольшое количество, которое вы выбрали в соответствии с ожидаемой точностью.

2

Как вы обнаружили, при сравнении чисел с плавающей запятой существует уровень неточности. Обычный способ проверки «равенство», чтобы определить разумную сумму разницы вы хотите принимать (обычно называемый «эпсилон») сравнить разницу между двумя числами от этой максимальной погрешности:

epsilon = 1E-14 

print(alpha, omega) 
print(alpha == omega) 
print(abs(alpha - omega) < epsilon) 
+0

Отказ от ответственности: я не программист на Python, поэтому мой синтаксис может быть немного выключен. –

1

Сначала вы следует заметить, что аргументы тригонометрических функций задаются по длине дуги, а не по степени. Таким образом, theta = -30 относится к углу -30 * 180/pi в градусах.

Во-вторых, процессор и, следовательно, вызывающая математическая библиотека имеют отдельные внутренние процедуры для вычисления tan и (sin, cos). Операция дополнительного деления теряет от 1/2 до 1 бит точности, что объясняет разницу в результатах.

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