[Python-Dev] histerical math.log(zero)

Tim Peters tim.one at comcast.net
Mon Aug 4 13:31:28 EDT 2003

[Samuele Pedroni]
> math.log raises different unrelated exceptions depending on the type
> of a zero argument:

It may, and probably does on most platforms.  Which exception gets raised
for a float 0.0, and even whether an exception gets raised at all in that
case, depends on what the platform libm does.  Standard C allows a lot of
variation here.

>  >>> math.log(0)
> Traceback (most recent call last):
>    File "<pyshell#1>", line 1, in -toplevel-
>      math.log(0)
> OverflowError: math range error
>  >>> math.log(0L)

Python handles log(long) itself, so the exception in this case is

> Traceback (most recent call last):
>    File "<pyshell#2>", line 1, in -toplevel-
>      math.log(0L)
> ValueError: math domain error
>  >>> math.log(0.0)
> Traceback (most recent call last):
>    File "<pyshell#4>", line 1, in -toplevel-
>      math.log(0.0)
> OverflowError: math range error
> should this stay this way?

Unless we write our own libm, consistency is hopeless.  Note that the 2.3
docs (for the math module) address this up-front:

   Note:  The math module consists mostly of thin wrappers around the
   platform C math library functions. Behavior in exceptional cases is
   loosely specified by the C standards, and Python inherits much of
   its math-function error-reporting behavior from the platform C
   implementation. As a result, the specific exceptions raised in
   error cases (and even whether some arguments are considered to be
   exceptional at all) are not defined in any useful cross-platform
   or cross-release way. For example, whether math.log(0) returns
   -Inf or raises ValueError or OverflowError isn't defined, and in
   cases where math.log(0) raises OverflowError, math.log(0L) may
   raise ValueError instead.

CPython started life with "classic" (pre-754) libms, where ERANGE got mapped
to OverflowError and EDOM to ValueError.  I view 0 as not being in the
domain of log(), so deliberately raised ValueError for a 0L argument.  The
best thing to do in an IEEE-754-ish system is probably to raise
ZeroDivisionError (whose generalized meaning isn't literally division by 0,
but "there's a singularity here"); and, indeed, the C99 standard requires
that implementations choosing to support the 754 gimmicks must raise the 754
divide-by-0 exception (and return minus infinity) for log(+0) and log(-0).

    y'rs  - tim

More information about the Python-Dev mailing list