-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.1a2
AM 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