Python cosine function precision [duplicate]

2019-07-21 21:45发布

问题:

This question already has an answer here:

  • Is floating point math broken? 30 answers

From mathematics we know that the cosine of a 90 degree angle is 0 but Python says it's a bit more than that.

import math
math.cos(math.radians(90))
6.123233995736766e-17

What's the matter between Python and the number "0"?

回答1:

Repeat after me:

Computers cannot process real numbers.

Python uses double precision IEEE floats, which round to 53 binary digits of precision and have limits on range. Since π/2 is an irrational number, the computer rounds it to the nearest representable number (or to a close representable number — some operations have exact rounding, some have error greater than 1/2 ULP).

Therefore, you never asked the computer to compute cos(π/2), you really asked it to compute cos(π/2+ε), where ε is the roundoff error for computing π/2. The result is then rounded again.

Why does Excel (or another program) show the correct result?

Possibility 1: The program does symbolic computations, not numeric ones. This applies to programs like Mathematica and Maxima, not Excel.

Possibility 2: The program is hiding the data (most likely). Excel will only show you the digits you ask for, e.g.,

>>> '%.10f' % math.cos(math.radians(90))
'0.0000000000'

Python has a finely tuned function for printing out floats so that they survive a round trip to text and back. This means that Python prints more digits by default than, for example, printf.

Possibility 3: The program you are using had two round-off errors that canceled.



回答2:

As Dietrich points out, the included Math package uses numerical approximations to calculate trig functions - pi has some level of precision represented through a float. But there are a bunch of good python packages for doing symbolic calculations too - Sympy is an easy way do more precise calculations, if you'd like.

consider:

import math
math.cos( 3*math.pi/2 )
# Outputs -1.8369701987210297e-16

as apposed to

import sympy
sympy.cos( 3*sympy.pi/2 ) 
# Outputs 0

There aren't a lot of cases where this makes a difference, and sympy is considerably slower. I tested how many cosine calculations my computer could do in five seconds with math, and with sympy, and the it did 38 times more calculations with math. It depends what you're looking for.