[Openmcl-devel] Negative number to positive whole-number float exponent

Liam Healy lnp at healy.washington.dc.us
Sat Apr 4 18:28:14 PDT 2009

On Sat, Apr 4, 2009 at 8:48 PM, Gary Byers <gb at clozure.com> wrote:
> On Sat, 4 Apr 2009, Liam Healy wrote:
>> A negative number to a positive whole-number exponent is real.
> CLHS says (in the dictionary entry for EXP and EXPT):
> "The result of expt can be a complex, even when neither argument is a
> complex, if base-number is negative and power-number is not an
> integer. The result is always the principal complex value."
> Your example seems to be covered by this (1.0d0 is not an integer
> ...), and even the weakest reading of "can be" that I can come up with
> seems to indicate that either a real or complex result is correct in
> this case.

I guess that depends on how you read "is not an integer".
Does that mean "is not of integer type" or
"is not numerically an integer value"?  If the former, you are
correct; if the latter, then that 1.0d0 is an integer numerically
(but not in type) so this escape clause doesn't apply.

>> In CCL 1.2, when the exponent is a float, there value is complex
>> with a small imaginary part.  This is undesirable; can it be fixed?
> Why is it undesirable, and why would changing it constitute "fixing" it ?
> (There might be good answers to these questions; I don't know.)

Taking a mathematical point of view: a negative number raised to
a positive whole-number power (I'm avoiding the overloaded term
"integer" here on purpose) is a real number, exactly.   Since
a whole number can be represented exactly in a float, there
isn't really a reason to return an imaginary part.  You could argue
that it is still permitted to be complex, but then it should be
#C(-1.0d0 0.0d0)
>From your tests below, it appears CLISP does this.

C doesn't have complex return from pow; it will signal an error
       EDOM   The argument x is negative and y is not an integral
value.  This would result in a com‐
              plex number.
and yet it is taking two doubles as arguments, so it is
able to distinguish an whole-number exponent (but
still of type double) from one that is not.
It would be nice if CL, which can return a complex number,
behaved identically to pow over the range of values that pow
can take without signalling an error.

(Again, I'm not saying that CCL violates the standard,
I'm just claiming it's preferable.)

> A very quick unscientific survey:
> clisp 2.46:
> [1]> (expt -1.0d0 1.0d0)
> #C(-1.0d0 0.0d0)
> LW 5.1:
> CL-USER 1 > (expt -1.0d0 1.0d0)
> #C(-1.0D0 1.2246063538223773D-16)
> sbcl 1.0.22
> * (expt -1.0d0 1.0d0)
> -1.0d0
> AllegroCL 8.1:
> CL-USER(1): (expt -1.0d0 1.0d0)
> #C(-1.0d0 1.2246467991473532d-16)
> It's hard to see how code could reliably and portably predict whether
> the result is real or complex in this case, since at least one
> implementation
> seems to return a real result (and the weak reading of "... can be ..."
> suggests that this is perfectly legal.)

I agree with you on that, but I still think it is desirable to return
a real when the exponent is a whole number, regardless of what
CL implementation you are using.

So I guess there are two issues here: should it return a real?
I think so, but I can see how one reading of the standard
permits otherwise (but still I think that's not as desirable),
and should the imaginary part be exactly zero?
and I think that this is more desirable than some numerical
noise because it is mathematically correct.

Thanks for looking into this minor issue.


>> Welcome to Clozure Common Lisp Version 1.2-r10552  (LinuxX8664)!
>> ? (expt -1.0d0 1.0d0)
>> #C(-1.0D0 1.2246467991473532D-16)
>> ? (expt -1.0d0 1)
>> -1.0D0
>> Thank you.
>> Liam

More information about the Openmcl-devel mailing list