-1.23+4.56iwhere -1.23 is the real and 4.56 the imaginary component. Conversion from/to this string rep and a list of {real imaginary} is done with
complex::scan (string) complex::format (real) (im)The imaginary factor may be an empty string if it amounts to 1 (e.g. 2+i), but must be signed with "+" or "-". For the rest, just see for yourself...}Code
namespace eval complex {
proc scan s {
regexp {^(-?([0-9]*\.)?[0-9]+)?(([+-]([0-9]*\.)?[0-9]*)i)?$} $s -> re - - im
if {$re==""} {set re 0}
switch -- $im {
"" {set im 0}
+ {set im 1}
- {set im -1}
}
list $re [expr {$im}] ;# expr may strip a plus sign
}
proc format {re {im 0}} {
if {!$im} {return $re}
subst $re[signof $im][expr {abs($im)==1?"":abs($im)}]i
}
proc signof x {expr {$x<0?"-":"+"}}
proc re x {lindex [scan $x] 0}
proc im x {lindex [scan $x] 1}
proc abs x {expr hypot([join [scan $x] ,])} ;# no bracing with join
proc + {x y} {
foreach {a b} [scan $x] {c d} [scan $y] break
format [expr {$a+$c}] [expr {$b+$d}]
}
proc - {x y} {
foreach {a b} [scan $x] {c d} [scan $y] break
format [expr {$a-$c}] [expr {$b-$d}]
}
proc * {x y} {
foreach {a b} [scan $x] {c d} [scan $y] break
format [expr {$a*$c-$b*$d}] [expr {$a*$d+$b*$c}]
}
proc / {x y} {
foreach {a b} [scan $x] {c d} [scan $y] break
set div [expr {double($c*$c+$d*$d)}]
format [expr {($a*$c+$b*$d)/$div}] [expr {($b*$c-$a*$d)/$div}]
}Examples proc test {} {
foreach test [split {
scan 1.23+4.56i
scan -1.35
format 1.23 4.56
format -1.23 -4.56
re -47.1-11i
im -1.23+4.56i
abs 3+4i
+ 3+i 1+2i
- 3+i 1+2i
\* 3+4i 1+2i
\* +i +i ;# -1
/ 2+5i -6-2i
} \n] {
puts -nonewline "$test => "
puts [eval $test]
}
}
}
puts [time complex::test 10] ;# took 91..121 msec on my P2/200/W95/8.1a2AM Here is a Straightforward implementation of complex numbers, aimed at practical use (that is: it expects complex numbers to be in preprocessed form)
Years later, RS redid it much simpler in Complex math with TOOT

