Version 9 of A little slide-rule

Updated 2003-09-04 07:46:05

if 0 {Richard Suchenwirth 2003-08-31 - The slide rule was an analog, mechanical device for approximate engineering computing, made obsolete by the pocket calculator since about the 1970-80s. The basic principle is that multiplication is done by adding logarithms, hence most of the scales are logarithmic, with uneven increments.

http://mini.net/files/sliderule.jpg

This fun project recreates a slide rule (roughly an Aristo-Rietz Nr. 89 with 7 scales - high-notch ones had up to 24) with a white "body" and a beige "slide" which you can move left or right with mouse button 1 clicked, or in pixel increment with the <Shift-Left>/<Shift-Right> cursor keys. Finally, the blue line represents the "mark" (how is that correctly called? "runner"? "slider"?) which you can move with the mouse over the whole thing to read a value. Fine movements with <Left>/<Right>.

Due to rounding errors (integer pixels), this plaything is even less precise than a physical slide rule was, but maybe you still enjoy the memories... The screenshot shows how I found out that 3 times 7 is approx. 21... (check the A and B scales).

For another mathematical toy, see TkSoroban. }

 proc ui {} {
    set width 620
    pack [canvas .c -width $width -height 170 -bg white]
    pack [label .l -textvariable info -fg blue] -fill x
    .c create rect 0 50 $width 120 -fill grey90
    .c create rect 0 50 $width 120 -fill beige -outline beige \
        -tag {slide slidebase}
    .c create line 0 0 0 120 -tag mark -fill blue
    drawScale .c K  x3    10 5    5 log10 1 1000 186.6666667
    drawScale .c A  x2    10 50  -5 log10 1 100 280
    drawScale .c B  x2    10 50   5 log10 1 100 280 slide
    drawScale .c CI 1/x   10 90 -5 -log10 1 10  560 slide
    drawScale .c C  x     10 120 -5 log10 1 10  560 slide
    drawScale .c D  x     10 120  5 log10 1 10  560 
    drawScale .c L "lg x" 10 160 -5 by100  0 10   5600
    bind .c <Motion> {.c coords mark %x 0 %x 170; set info [values .c]}
    bind .c <1> {set x %x}
    bind .c <B1-Motion> {%W move slide [expr {%x-$x}] 0; set x %x}
    bind . <Shift-Left>  {.c move slide -1 0; set info [values .c]}
    bind . <Shift-Right> {.c move slide  1 0; set info [values .c]}
    bind . <Left>  {.c move mark -1 0; set info [values .c]}
    bind . <Right> {.c move mark  1 0; set info [values .c]}
 }
 proc drawScale {w name label x y dy f from to fac {tag {}}} {
    set color [expr {[string match -* $f]? "red": "black"}]
    $w create text $x [expr $y+2*$dy] -text $name -tag $tag -fill $color
    $w create text 600 [expr $y+2*$dy] -text $label -tag $tag -fill $color
    set x [expr {[string match -* $f]? 580: $x+10}]
    set mod 5
    set lastlabel ""
    set lastx 0
    for {set i [expr {$from*10}]} {$i<=$to*10} {incr i} {
        if {$i>100} {
            if {$i%10} continue ;# coarser increments
            set mod 50
        }
        if {$i>1000} {
            if {$i%100} continue ;# coarser increments
            set mod 500
        }
        set x0 [expr $x+[$f [expr {$i/10.}]]*$fac]
        set y1 [expr {$i%(2*$mod)==0? $y+2.*$dy: $i%$mod==0? $y+1.7*$dy: $y+$dy}]
        set firstdigit [string index $i 0]
        if {$y1==$y+$dy && abs($x0-$lastx)<2} continue
        set lastx $x0
        if {$i%($mod*2)==0 && $firstdigit != $lastlabel} {
            $w create text $x0 [expr $y+3*$dy] -text $firstdigit \
               -tag $tag -font {Helvetica 7} -fill $color
            set lastlabel $firstdigit
        }
        $w create line $x0 $y $x0 $y1 -tag $tag -fill $color
    }
 }
 proc values w {
    set x0 [lindex [$w coords slidebase] 0]
    set x1 [lindex [$w coords mark] 0]
    set lgx [expr {($x1-20)/560.}]
    set x [expr {pow(10,$lgx)}]
    set lgxs [expr {($x1-$x0-20)/560.}]
    set xs [expr {pow(10,$lgxs)}]
    set res     K:[format %.2f [expr {pow($x,3)}]]
    append res "  A:[format %.2f [expr {pow($x,2)}]]"
    append res "  B:[format %.2f [expr {pow($xs,2)}]]"
    append res "  CI:[format %.2f [expr {pow(10,-$lgxs)*10}]]"
    append res "  C:[format %.2f $xs]"
    append res "  D:[format %.2f $x]"
    append res "  L:[format %.2f $lgx]"
 }
 proc pow10 x {expr {pow(10,$x)}}
 proc log10 x {expr {log10($x)}}
 proc -log10 x {expr {-log10($x)}}
 proc by100  x {expr {$x/100.}}
 #--------------------------------
 ui
 bind . <Escape> {exec wish $argv0 &; exit}

Judging from some web sites, it appears as if the parts of a slide-rule are called "stator" (big white), "slide" (thin beige), and "cursor" (transparent little thing, blue line in the above example). Also, there's a roughly comparable emulation in Java at http://www.cs.utsa.edu/~wagner/slide/Slide5.html


Absolutely Amazing for such little code! Nicely DONE!


AM I can add a personal touch to the end of the slide-rule era:

When I took my final exams in secondary school (in 1978-79), there was a debate whether electronic calculators should be allowed. The decision was no, because they were still pretty expensive at the time and allowing them might force students who did not yet have one to buy such a thing.

It was, however, a prequisite when I went to university in that same year. After school I have used it sporadically, but I envy my father for his possessing a very smooth wooden slide-rule in a nice wooden casing.

This page inspired me to look into another obsolete instrument, the klepsydra.


Arts and crafts of Tcl-Tk programming