[Tutor] the binary math "wall"
Dave Angel
davea at ieee.org
Tue Apr 20 20:45:50 CEST 2010
Lowell Tackett wrote:
> I'm running headlong into the dilemma of binary math representation, with game-ending consequences, e.g.:
>
>
>>>> 0.15
>>>>
> 0.14999999999999999
>
> Obviously, any attempts to manipulate this value, under the misguided assumption that it is truly "0.15" are ill-advised, with inevitable bad results.
>
> the particular problem I'm attempting to corral is thus:
>
>
>>>> math.modf(18.15)
>>>>
> (0.14999999999999858, 18.0)
>
> with some intermediate scrunching, the above snippet morphs to:
>
>
>>>> (math.modf(math.modf(18.15)[0]*100)[0])/.6
>>>>
> 1.6666666666664298
>
> The last line should be zero, and needs to be for me to continue this algorithm.
>
> Any of Python's help-aids that I apply to sort things out, such as formatting (%), or modules like "decimal" do nothing more than "powder up" the display for visual consumption (turning it into a string). The underlying float value remains "corrupted", and any attempt to continue with the math adapts and re-incorporates the corruption.
>
> What I'm shooting for, by the way, is an algorithm that converts a deg/min/sec formatted number to decimal degrees. It [mostly] worked, until I stumbled upon the peculiar cases of 15 minutes and/or 45 minutes, which exposed the flaw.
>
> What to do? I dunno. I'm throwing up my hands, and appealing to the "Council".
>
> (As an [unconnected] aside, I have submitted this query as best I know how, using plain text and the "Tutor at ..." address. There is something that either I, or my yahoo.com mailer *or both* doesn't quite "get" about these mailings. But, I simply do my best, following advice I've been offered via this forum. Hope this --mostly-- works.)
>
> >From the virtual desk of Lowell Tackett
>
>
>
One of the cases you mention is 1.6666666 The decimal package won't
help that at all. What the decimal package does for you is two-fold:
1) it means that what displays is exactly what's there
2) it means that errors happen in the same places where someone
doing it "by hand" will encounter.
But if you literally have to support arbitrary rational values
(denominators other than 2 or 5), you would need to do fractions, either
by explicitly keeping sets of ints, or by using a fractions library.
And if you have to support arbitrary arithmetic, there's no answer other
than hard analysis.
This is not a Python-specific problem. Floating point has had such
issues in every language I've dealt with since 1967, when I first
learned Fortran. If you compare two values, the simplest mechanism is
abs(a-b) < delta
where you have to be clever about what small value to use for delta.
If all values are made up of degrees/minutes/seconds, and seconds is a
whole number, then store values as num-seconds, and do all arithmetic on
those values. Only convert them back to deg/min/sec upon output.
DaveA
More information about the Tutor
mailing list