[Tutor] the binary math "wall"

Steven D'Aprano steve at pearwood.info
Wed Apr 21 23:48:08 CEST 2010


On Thu, 22 Apr 2010 01:37:35 am Lowell Tackett wrote:

> Recalling (from a brief foray into college Chem.) that a result could
> not be displayed with precision greater than the least precise
> component that bore [the result].  So, yes, I could accept my input
> as the arbitrator of accuracy.

Unfortunately, you can't distinguish the number of supplied digits of 
accuracy from a float. Given as floats, all of the following are 
identical:

0.1
0.10000
0.099999999999999999
0.100000000000000001

as are these two:

0.099999999999999998
0.099999999999999985

Perhaps you should look at the Decimal class, not necessarily to use it, 
but to see what they do. For instance, you create a Decimal with a 
string, not a float:

>>> from decimal import Decimal
>>> Decimal('0.1')
Decimal("0.1")
>>> Decimal('0.10000')
Decimal("0.10000")

which allows you to distinguish the number of digits of precision.


> A scenario:
>
> Calculating the coordinates of a forward station from a given base
> station would require [perhaps] the bearing (an angle from north,
> say) and distance from hither to there.  Calculating the north
> coordinate would set up this relationship, e.g.:
>
> cos(3° 22' 49.6") x 415.9207'(Hyp) = adjacent side(North)
>
> My first requirement, and this is the struggle I (we) are now engaged
> in, is to convert my bearing angle (3° 22' 49.6") to decimal degrees,
> such that I can assign its' proper cosine value.

This is MUCH MUCH MUCH easier than trying to deal with DMS as a float. 
Your data already separates the parts for you, so it is just a matter 
of:

>>> d = 3 + 22/60.0 + 49.2/3600.0
>>> import math
>>> angle = math.radians(d)
>>> math.cos(angle)
0.9982601259166638

Then the only problem you have is whether or not the formula you are 
using is numerically stable, or whether it is subject to 
catastrophically growing errors.

I hope we're not frightening you off here. For nearly anything people 
are going to want to do, their input data will be in single-precision. 
One of the simplest things they can do to improve the accuracy of 
floating point calculations is to do their intermediate calculations in 
double-precision.

The good news is, Python floats are already in double-precision.

For most modern systems, single-precision floats have 24 binary digits 
of precision (approximately 6 decimal digits) and double-precision 
floats have 53 binary digits (15 decimal) of precision. More than 
sufficient for dealing with an angle measured to a tenth of a second.


Some resources for you to read:

http://en.wikipedia.org/wiki/Floating_point
http://www.cs.princeton.edu/introcs/91float/
http://www.cs.berkeley.edu/~wkahan/
http://docs.sun.com/source/806-3568/ncg_goldberg.html



> Were I to accumulate many of these "legs" into perhaps a 15 mile
> traverse-accumulating little computer errors along the way-the end
> result could be catastrophically wrong.

YES!!! 

And just by being aware of this potential problem, you are better off 
than 90% of programmers who are blithely unaware that floats are not 
real numbers.




-- 
Steven D'Aprano


More information about the Tutor mailing list