Version 26 of Engineering Notation

Updated 2006-12-14 23:59:14

A way to convert any arbitrary number to engineering notation [L1 ]

 # eng - return engineering notation of any given number in a 2 element list as {num eng_unit}
 # pico nano micro milli 1 kilo Mega Giga Tera
 # use: eng <num> <unit>   eg. eng 123.456E6 Hz
 # First - scan to check if n is a number, if not then just return with input given {n u}
 proc eng {n u} {
        if ![scan $n %g res] {return [list $n {} $u]}
        if [expr $n>=1E-12 && $n<1E-9] {list [expr $n*1E12] p$u} \
        elseif [expr $n>=1E-9 && $n<1E-6] {list [expr $n*1E9] n$u} \
        elseif [expr $n>=1E-6 && $n<1E-3] {list [expr $n*1E6] u$u} \
        elseif [expr $n>=1E-3 && $n<1] {list [expr $n*1E3] m$u} \
        elseif [expr $n>=1 && $n<1E3] {list [format %g $n] $u} \
        elseif [expr $n>=1E3 && $n<1E6] {list [expr $n/1E3] k$u} \
        elseif [expr $n>=1E6 && $n<1E9] {list [expr $n/1E6] M$u} \
        elseif [expr $n>=1E9 && $n<1E12] {list [expr $n/1E9] G$u} \
        elseif [expr $n>=1E12 && $n<1E15] {list [expr $n/1E12] T$u} \
        else {list [format %g $n] $u}
 }
 ### Example Output
 %eng 1.23456E-2 V
 12.3456 mV
 %eng 209357.209857E5 Hz
 20.9357209857 GHz
 %eng 0.012e-7 H
 1.2 nH

CvK (Dec 2006) - is there any way this could be simplified ?

Bryan Oakley notes: that's a lot of unbraced expressions! MJ - even more so if you consider that if and elseif pass the first following argument to expr as well. Always brace your expr-essions.

For that matter, "if [expr ..." is a bit redundant.

AMG: The rampant indenting was hurting my eyes, so I removed it. This version should be a bit easier to read.

MJ - Try the following (with the additional benefit that it is easier to add more powers of 1000):

 proc eng {num u} {
        array set orders {
         -8 y -7 z -6 a -5 f -4 p -3 n -2 u -1 m 0 {} 1 k 2 M 3 G 4 T 5 P 6 E 7 Z 8 Y
        }
        set numInfo  [split [format %e $num] e]
        set order [expr {[scan [lindex $numInfo 1] %d] / 3}]
        if {[catch {set orders($order)} prefix]} {return [list $num $u]}
        set num [expr {$num/(10.**(3*$order))}]
        return [list $num $prefix$u]
 }

CvK - MJ, your solution seems much better and more readable. I agree that the nested "if [expr .." is redundant. Syntax highlighting helped with the aesthetics of indentation which is lost with the pre-formatting in this wiki. I tried your example but it gave a syntax error ...

 syntax error in expression "$num/(10.**(3*$order))": unexpected operator *

[ Category Mathematics ]