Hi!
A short question about the EXPT function in CL:
Can anybody explain the following behaviour to me ?
> (EXPT -2.0 2)
4.0
> (EXPT -2.0 2.0)
#C(4.0 6.993822E-7)
> (EXPT 2.0 2.0)
4.0
Why returns EXPT a complex number if there's a negative base and a
floating power ?
Cheers
Andy
******** Geodaetisches Institut, RWTH Aachen, Templergraben 55, D-52056
Aachen
****** TEL: +49 (0)241 80-5283 FAX: +49 (0)241 8888-142
**** E-MAIL: ·······@gia.rwth-aachen.de
Hi,
On Fri, 21 Nov 1997 15:11:06 +0100, Andy Brezing
<·······@gia.rwth-aachen.de> wrote:
>Why returns EXPT a complex number if there's a negative base and a
>floating power ?
I want to quote the Common Lisp Hyper Spec (available through
www.harlequin.com):
-----------------------[CL Hyper Spec]---------------------------------
...
expt base-number power-number => result
...
expt returns base-number raised to the power power-number. If the
base-number is a rational and power-number is an integer, the calculation
is exact and the result will be of type rational; otherwise a
floating-point approximation might result. For expt of a complex rational
to an integer power, the calculation must be exact and the result is of
type (or rational (complex rational)).
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.
....
-----------------------[CL Hyper Spec]---------------------------------
You will find the same explanation in CLTL2 on pages 300/301.
Greetings
Federico
········@hrzpub.tu-darmstadt.de (Federico Hernandez-Pueschel) writes:
> On Fri, 21 Nov 1997 15:11:06 +0100, Andy Brezing
> <·······@gia.rwth-aachen.de> wrote:
> >Why returns EXPT a complex number if there's a negative base and a
> >floating power ?
> -----------------------[CL Hyper Spec]---------------------------------
...
> 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.
> ....
> -----------------------[CL Hyper Spec]---------------------------------
>
As a description of the implementation, this quote is not terribly
satisfying, mathematically. It is important to note that a
floating-point power-number is an approximation. In this case, 2.0
represents all reals between approximately 1.99999997 and 2.00000003.
It should be clear that -2.0 to the power of most of those reals will
be complex.
> (EXPT -2.0 2.0)
#C(4.0 6.993822E-7)
Whether #C(4.0 6.993822E-7) is the "best" representative from the
region described by the given expression I'll leave to those who can
do complex mappings better than I.
- Patrick
Andy Brezing <·······@gia.rwth-aachen.de> writes:
> Hi!
>
> A short question about the EXPT function in CL:
> Can anybody explain the following behaviour to me ?
>
> (EXPT -2.0 2 ) => 4.0
> (EXPT -2.0 2.0) => #C(4.0 6.993822E-7)
> (EXPT 2.0 2.0) => 4.0
>
> Why returns EXPT a complex number if there's a negative base and a
> floating power ?
It's important to separate two questions here:
(a) What are floats mathematically? I may not be the best person
to answer since math was never my strongest suit, but my best
understanding is that they are most appropriately viewed as
rational numbers sparsely and irregularly spaced in a plane
such that they serve as proxies for all nearby numbers, whether
rational or irrational. When dealing in complex floats, the
notion of "nearby" becomes even more (if you'll pardon the pun)
complex. One hopes that the very nearest float to the
mathematically correct one will be found, but one also hopes
that this decision will be made with no additional computation
in the blink of an eye. (Seems to me that given the irregular
placement of represented numbers in the total space of numbers,
it's virtually magic that this can ever be done correctly, much
less in a constant, extremely small amount of time.) But
sometimes one presumably misses and sometimes errors accumulate
so presumably even the optimal mathematical result is tough to
discern without knowing the whole space of subsequent operations
you plan to do so that errors could be designed to cancel each
other rather than magnify each other. Of course, I guess the
problem is that being "just a little bit complex" has implications
that may be non-trivial. In cases where you have reason to believe
a result would be better off not "going complex" I suppose you
could anticipate that little bit of imaginary and lop it off;
maybe you have enough additional information about your domain to
know this is safe where you seem to be expecting the Lisp system
to do it but it can't because it doesn't have that extra bit of
domain knowledge... (Then again, maybe you're just confused and
Lisp is reminding you it's not as clear as you're thinking. :-)
(b) What is the difference between a language and an implementation?
Even if you know the answer you want, a given processor might
or might not have an operation that gives it. The spec often
leaves a considerable latitude to the implementation in order
to allow the implementation to use its native arithmetic and
system libraries instead of forcing time-consuming simulation,
possibly requiring expensive hand-coding. One should NEVER
try a function a few times, observe experimentally the result,
and then conclude something like (as above) "returns a complex
if there's a negative base and a floating power". As painful as
it seems, you should say "appears to return a complex in some
particular release of some particular implementation on some
particular hardware under some particular operating system
if there's a negative base and a floating power". That is, the
function EXPT is a linguistic entity defined externally of the
language. It does precisely what the definition says because
it is a constraint, not an implementation, and because an
implementor is free to move among techniques that do not violate
the constraints. Also, there may be things you're not seeing,
so unless you are sure you've exhaustively tried all possible
inputs under all possible circumstances, it's unwise to
generalize without at least noting that you've done so. And,
finally, if Lisp calls out to the operating system and hardware,
the answer may be in those elements, and not Lisp at all.
As a designer of Lisp (the language) myself, I routinely get
questions which sound like "language questions" but really
turn out to be "implementation questions". That is, why did
the implementor choose to inhabit this part of the space and
not that. My answer is always, "Because he was permitted to
inhabit any part of the space he wanted to." I can't tell if
you're saying the space is too large (that would be a language
issue) or the choice is just puzzling (no one's bug, but an
implementor's job to answer) or the choice is a bad position in
the space (maybe a language issue, but often more easily
controlled by bug reports to the vendor than bug reports to
the language--often the language prefers to leave "efficiency"
choices to the free market to sort out) or...
Well, I hope those two perspectives help you somewhat in sorting
this out.