Wondercricket
Wondercricket

Reputation: 7872

Python trig functions not returning matched results

I came across something rather interesting while I am playing around with the math module for trigonometric calculations using tan, sin, and cos.

As stated is all math textbooks, online source, and courses, the following is true:

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

Although I came across some precision errors while using the three trig functions with the following:

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)

I have tried a couple of different values for theta and the last digit of the results has been off by a tiny bit.

Is there something that I am missing?

Upvotes: 1

Views: 214

Answers (3)

Lutz Lehmann
Lutz Lehmann

Reputation: 25992

First you should notice that the arguments of trigonometric functions are given in arc length, not in degree. Thus theta=-30 refers to an angle of -30*180/pi in degrees.

Second, the processor, and thus the calling math library, has separate internal procedures for the computation of tan and (sin, cos). The extra division operation loses 1/2 to 1 bit of precision, which explains the difference in results.

Upvotes: 1

D Stanley
D Stanley

Reputation: 152566

As you have discovered, there is a level of imprecision when comparing floating point numbers. A common way to test for "equality" is to determine a reasonable amount of difference you want to accept (commonly called "epsilon") an compare the difference between the two numbers against that maximum error:

epsilon = 1E-14

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

Upvotes: 2

xnx
xnx

Reputation: 25528

This issue is because of the finite floating point precision (not all real numbers can be represented exactly and not all calculations with them are precise). An accessible guide is in the Python docs.

Using the default, "double precision" floating point representation, you can never hope for better than about 15 decimal place precision and calculations involving such numbers will tend to degrade this precision (the rounding error refered to in the above comment). In the same way, you get False from the following:

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

because the Python isn't squaring 0.1 but the "nearest representable number" to 0.1, which is neither 0.01 nor the nearest representable number to 0.01.

D Stanley has given the correct way to test for "equality" within some absolute tolerance: (abs(a-b) < tol) where tol is some small number you choose to fit your expected precision.

Upvotes: 3

Related Questions