HELP: restore my faith in Python
Tim Peters
tim_one at email.msn.com
Sun Mar 12 10:45:22 CET 2000
[Ken Seehof, wants "int" to round floats in some way]
> ...
> Python is supposed to work for non-computer geeks.
Moving to rationals would give the illusion of repairing that; at least
until rationals bite them with their own brand of surprises.
> ...
> My solution works for people who:
No, you don't have a solution -- or, if you do, you're holding back <wink>.
You have a complaint, and an untested hope that some so-far unspecified form
of rounding would help.
It so happens I have unhappy years of actual experience with that approach:
Cray Research machines in the 80's didn't have "real division", they
approximated x/y by computing a reciprocal approximation to y, then
multiplying that by x. The approximation was such that 6./3. came out to a
tiny bit smaller than 2.0, so int(6./3.) came out as 1. The first Cray
Fortran compiler (CFT) eventually did exactly what you suggest, trying to
hide the flawed numerics by adding a fudge factor (with the appropriate
sign) to floats when they got converted to ints. People loved that at
first, but then one by one bumped into the deeper surprises, and complained
ever more bitterly. For a trivial example,
i = int(6./3.)
computed 2, but
equal = 6./3. == 2
computed false (in mixed comparisons, Fortran and Python both coerce to the
wider type, so this is *not* a case where 6./3. gets converted to 2, but a
case where 2 gets promoted to 2.0). For a subtler example,
i = int(6./3.*n)
was equal to 2*n for "small" values of n, but if you just *happened* to have
an n large enough to exaggerate the slight flaw in 6./3. beyond the limit of
the epsilon rounding gimmick to overcome, it "suddenly for no reason at all"
did not equal 2*n anymore. Make epsilon large enough to hide that in all
cases, and even int(1.1) would have to round up to 2!
After years of trying to patch over more & more surprises, nobody was quite
sure what any expression would compute anymore, and Cray's second Fortran
compiler (CFT77) didn't repeat any part of this mistake. Was worth a try
the first time, though <wink>.
IEEE-754 arithmetic is much better behaved than Cray's was, but the same
lesson applies: you can't hide one kind of flaw without introducing others
(btw, while 6.*(1./3.) is exactly 2 in 754 default double arithmetic,
98.*(1./49.) is a little smaller than 2). The fp experts on the 754
committee were extremely keen to make fp as unsurprising as possible, and
made some extremely unpopular (at the time) decisions in support of that
(for example, in 754 arithmetic, if x-y == 0 is true for finite x and y,
then x==y is also true; this requires that the HW support "gradual
underflow", which no FPU designer then or now really wants to pay for).
> ...
> BTW, my definition of correct is simply that floating point
> mimics real numbers,
That's the problem: they don't. Not even close. You can't hide that from
newbies or professionals. 754 pushed the attempt harder than anyone before
them, and the surprises that remain are "deep" properties of the approach
(754 repaired all the shallow ones, and sometimes at very signficant cost in
implementation complexity and expense).
Note that REXX defined its fp with newbies in mind, using base 10 instead of
base 2, giving a huge exponent range, and allowing the user to set the
precision. Note that newbies are *not* surprised that, e.g.,
x = 1./3.
y = x * 3.0
makes y come out to 0.99999999 in REXX, despite that it's just as absurdly
flawed (from the "mimic real numbers" POV) as anything in 754 binary
floating-point. They're simply *used* to this kind of error from hand
calculators and their own pencil-and-paper decimal arithmetic. So don't
assume that newbies are looking for "real numbers" either. It may be truer
to say that they're looking for the same mistakes they make <0.917 wink>.
start-them-when-they're-5-years-old-and-there's-nothing-too-bizarre-
to-be-accepted-by-age-6-as-the-only-correct-way-ly y'rs - tim
More information about the Python-list
mailing list