Subject: [clisp-list] reporting curious complex numbers appearance

From: lin8080 <[email-masked]>
Date: Mon Jul 14 13:16:08 2003

Hallo

There is something going not so like I expect. I wrote a simple code
(see below) to examine some numbers. It works well with floats and
integers, (also shows the stack overflow when the numbers are to big,
but I use small numbers, so this is no problem). 

Now, when I type in (rechne (sin 30)) it returns some numbers in the way
like complex numbers are shown. And I think there is something going
wrong ...

Here is the code:

(setq rechen (make-array '(9 3)))

(print "Bitte eingeben (rechne xx) - xx steht für eine Zahl")
; this is: "please input (rechne xx) where xx is your number"

(defun rechne (zahl)

   (setf x (* zahl zahl))   (setf (aref rechen 0 0) x)
   (setf y (sqrt zahl))     (setf (aref rechen 0 2) y)
  (setf (aref rechen 0 1) "   ")
   (setf x1 (* x y))        (setf (aref rechen 1 0) x1)
   (setf y1 (/ x y))        (setf (aref rechen 1 2) y1)
  (setf (aref rechen 1 1) "   ")
   (setf x2 (* x1 y1))      (setf (aref rechen 2 0) x2)
   (setf y2 (/ x1 y1))      (setf (aref rechen 2 2) y2)
  (setf (aref rechen 2 1) "   ")
   ....
   (setf x8 (* x7 y7))      (setf (aref rechen 8 0) x8)
   (setf y8 (/ x7 y7))      (setf (aref rechen 8 2) y8)
  (setf (aref rechen 8 1) "   ")
   (print rechen)
)

The input is: (rechne (sin 30))

The output looks like this:

#2A((0.9762065 "   " #C(0 0.993997
    (#C(0 0.9703471) "   " #C(0 -0
    (0.9529791 "   " -0.9880316)
    ....

Please check it out on other systems (mine is win98 on P133-128MB) and
when it is like an error please correct it.

so long
stefan

---

From: Sam Steingold <[email-masked]>
Date: Mon Jul 14 13:34:03 2003

1. what is CLISP version?
2. what is the output you expect?
3. what is the precise code you tried (no "...." please).

---

From: Kaz Kylheku <[email-masked]>
Date: Mon Jul 14 14:25:34 2003

> like complex numbers are shown. And I think there is something going

The input to the trigonometric functions in Lisp, and many other
programming languages, is expressed in radians, rather than degrees. It
is an instant ``red flag'' when someone is trying to take the sine of
30 in a programming example that doesn't work. :)

Radians are units based on the idea that the radius of a circle
represents one unit going around the circle. Hence there are (* 2 pi)
radians to 360 degrees, and 30 degrees is (/ pi 6) radians or
about 0.524.

The reason some numbers coming out of your program are shown in complex
notation is because they really *are* complex. The value of (sin 30) is
approx -0.988. The square root of that is a negative number.

In some programming languages, taking the square root of a negative
number triggers an error. Lisp is different and better; it produces a
complex number. This is one of the advantages of dynamic typing.

Dynamic typing allows a function to compute an object whose type is
based on the properties of its inputs; the restriction that a function
must have a rigid, compile-time ``return type'' is not imposed.

> (setq rechen (make-array '(9 3)))

This works as casual use in CLISP and other Lisp implementations, but
in serious Lisp programs you should use DEFVAR, DEFPARAMETER for
defining global variables.

It's not well-defined behavior to SETQ or SETF a symbol which has no
previously defined variable binding.

Also, unless you are working in your own package it's probably a good
idea to name global variables with a leading and trailing asterisk:

  (defvar *rechen* (make-array '(9 3)))

Use LET for local variables:

   (let ((x (* zahl zahl)))
     (setf (aref *rechen* 0 1) x))

But this really isn't any clearer than:

  (setf (aref *rechen 0 1)
        (* zahl zahl))

---

From: lin8080 <[email-masked]>
Date: Wed Jul 16 23:53:11 2003

> radians to 360 degrees, and 30 degrees is (/ pi 6) radians or

Yes, I know. I normaly use 57.3 to transform Grad in Radians. (x[rad] =
x * 57.3 [grad], y[grad] = y / 57.3 [rad]). Doing so, I get other
results (sin (/ 30 57.3)) vs (sin 30). 

> approx -0.988. The square root of that is a negative number.

This is what HyperSpec says in section SQRT, ISQRT (file
/body/fun_sqrtcm_isqrt.html.) "... if the number is not a complex but is
negative, then the result is a complex" (12.1. ff). This case seems to
be clear. 

The mathematicans also say that a negativ sqrt is complex (right?), but
the same mathematicans say that (sqrt) is the reverse function of (*
zahl zahl) (which will returned only positiv numbers) and they also
describe for what kind of numbers this is valid. 

The practical reason why there is +,- in trigononic functions, is to say
where the point of the graph is in the xy-system. And for that no
complex is needed, only 2 values.  

So the question should be: is there a way to suppress the complex number
representation in negative trigonomic values, when a sqrt is involved?  

> complex number. This is one of the advantages of dynamic typing.

Yes, right. I also see simple 0 instead of an error (some small
scheme-lisps). 

> previously defined variable binding.

Oh, this is more like my privat convention. For variables/symbols that
will not change I use the old  SETQ. The rest is SETF. And don't worry,
this code will not find a way into a package. It is only a quick hack to
see a series of digits is equal or not. The file names "zahl5.lsp" and
is executed as needed with (load ".."). Only when playing around I
realised the complex representation in trigonomic functions and I
reported this, because it makes me wonder how to interpret complex (sin
x) values and while there is a similar mail with maxima (sin x) here.

stefan

---

From: Pascal Bourguignon <[email-masked]>
Date: Thu Jul 17 07:26:31 2003

>describe for what kind of numbers this is valid. 

You have to take into account the domain of the function. To take the 
reverse function, you must consider the function only on a sub-domain 
where it's a bijection.

For example, if you consider: 

    f : ]-infinity, 0] ------> [0, +infinity[
                   x  |------> x*x

then the reverse is:

    f^-1 : [0, +infinity[ -----> ]-infinity, 0]
                   x     |-----> - sqrt(x)

Note that this other function:

    g : [0, +infinity[ ------> [0, +infinity[
                   x  |------> x*x

which looks a lot like f, has not the same reverse function!

And of course, a function square : R --> R, x |--> x*x is not a 
bijection, so it has no reverse.

So you see, you cannot expect the operators implemented in Lisp to 
correspond to the mathematical function you're manipulating.
In maths, there are a lot of square root function, all defined on a 
different domain, and with a different image set.

In computer languages we choose to implement one specific function, with 
a domain and image set considered useful. 

Since Lisp knows about complex, it naturally defines sqrt over the 
complexes and returns a complex (unless the imaginary part is null, in 
which case it's a real).

>representation in negative trigonomic values, when a sqrt is involved?  
Yes, define properly your functions, and implement them accordingly.

(defun my-square-over-R-plus (x)
  (assert (and (realp x) (<= 0 x)))
  (* x x))

(defun my-square-root-over-R-plus (x)
    (assert (and (realp x) (<= 0 x)))
    (sqrt x))

-- 
__Pascal Bourguignon__
mailto:[email-masked]
mailto:[email-masked]