[Python-bugs-list] float("1.0e-309") inconsistency on win32 (PR#245)

tim_one@email.msn.com tim_one@email.msn.com
Fri, 24 Mar 2000 23:51:03 -0500 (EST)


"In the face of ambiguity, refuse the temptation to guess".

That's one of the Pythonic Theses you're tempted to ignore too often <wink>.

Part of taking 754 seriously is that 754 gives the user complete control
over what happens in case of exceptions (including underflow):  ignore them,
raise a fatal error, or simply set a flag saying it occurred.
Unfortunately, we have to wait for C9x until there's a portable way to get
at that stuff.  Before then, it requires wildly varying platform-specific
hair.

> Hm, I'm not so sure.  Suppose I'm writing a program that reads a data
> files generated by some Fortran program.  The Fortran program is
> giving me points to plot for example.  If Fortran manages to output
> 1e-500, wouldn't it make more sense if I rounded that to zero instead
> of rejecting it?

This *may* make good sense if Python had certain knowledge that the program
is merely going to plot the points, but probably not even then.  That is,
"insignificantly small" is relative to the application, and e.g. for all we
know the Fortran program generated a million doubles *all* in the range
[1e-500, 10e-500]:  the intended plot of the data could very well be a
pointillistic version of the Mona Lisa rather than a straight line.

> After all, after converting to plot precision it's
> going to be zero anyway.

As above, this conclusion relies on the dubious assumption that 1e-500 is
very much smaller than the other values.

> This way I could almost defend using strtod() for literals in
> Python source code (where it makes more sense to warn about underflow)
> but atof() for input.  Except that of course input could conceivably
> be using eval()...
>
> Another argument for turning underflow into zero is that that also
> happens in regular arithmetic:
>
> >>> 0.1**2**8
> 1.0000000000000275e-256
> >>> 0.1**2**9
> 0.0

Which is often desired but sometimes a disaster -- the language simply can't
guess.  On whatever machine you ran this on, it almost certainly set the
"underflow happened" flag but continued on because the underflow exception
was masked out by default.

> I like this uniform behavior: overflow -> exception, underflow ->
> zero.  My calculator does this too.

Not mine <wink>.  Really, whether underflow gripes is controlled by a
user-settable flag on high end HP calculators.  Note too that neither does
float *overflow* raise an exception under most Pythons today:

D:\Python>python
Python 1.5.42 (#0, Jan 31 2000, 14:05:14) [MSC 32 bit (Intel)] on win32
Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam
>>> 1e500
1.#INF
>>> 1e200**2
1.#INF
>>>

I personally favor raising exceptions (by default) on 754's overflow, divide
by 0, and invalid operation conditions, while (again by default) letting
underflow and inexact pass without comment.  But it again requires fiddling
the HW's 754 control registers to make that happen.  P3K, not now.

> Am I hopelessly naive about this?

Not *entirely* hopeless, but close <wink>.  If we ever talk about it for an
hour, I'll convince you of the futility of fighting 754.  They beat all
resistance out of me in a mere decade <0.5 wink>.

> What else can we do?

Not much!  Switching uniformly to either atof() or strtod() would be OK by
me for now, although I don't think patching over the current inconsistency
buys enough bang for the buck to be worth the effort.

> What control does C give?

None, until C9X.

> What does sscanf() do?

I don't care -- ANSI C predated 754's absolute universal triumph, and ANSI
C's numerics fight the *right* thing to do now just about every step of the
way.  C9x is supposed to fix all that.

In the meantime, I think what JPython does is much more interesting (but
don't know what that is):  whatever we do here should be consistent with The
Other Python too, and Java has a much better 754 story than ANSI C.  754 is
here to stay, but the last iteration of ANSI C isn't.  Best guess is that
Java acts more like atof than strtod in this case.