The first algorithm is from Chart generation support by Dave Griffin.
#
# nice_number
#
# Reference: Paul Heckbert, "Nice Numbers for Graph Labels",
# Graphics Gems, pp 61-63.
#
# Finds a "nice" number approximately equal to x.
#
# Args: x -- target number
# round -- If non-zero, round. Otherwise take ceiling of value.
proc nice_number {x {round 0}} {
# expt -- Exponent of x
# frac -- Fractional part of x
# nice -- Nice, rounded fraction
set expt [expr {floor(log10($x))}]
set frac [expr {$x / pow(10.0, double($expt))}]
if ($round) {
if {$frac < 1.5} {
set nice 1.0
} elseif {$frac < 3.0} {
set nice 2.0
} elseif {$frac < 7.0} {
set nice 5.0
} else {
set nice 10.0
}
} else {
if {$frac <= 1.0} {
set nice 1.0
} elseif {$frac <= 2.0} {
set nice 2.0
} elseif {$frac <= 5.0} {
set nice 5.0
} else {
set nice 10.0
}
}
return [expr {$nice * pow(10.0, double($expt))}]
}The second routine is from A little bar chart by the ubiquitous Richard Suchenwirth:
# An interesting sub-challenge was to round numbers very roughly,
# to 1 or maximally 2 significant digits - by default rounding up,
# add "-" to round down:}
proc Roughly {n {sgn +}} {
regexp {(.+)e([+-])0*(.+)} [format %e $n] -> mant sign exp
set exp [expr $sign$exp]
if {abs($mant)<1.5} {
set mant [expr {$mant*10}]
incr exp -1
}
set t [expr round($mant $sgn 0.49)*pow(10,$exp)]
expr {$exp>=0? int($t): $t}
}tklib plotchart has a similar routine that also computes a good tick interval.
package require plotchart
foreach {niceMin niceMax niceTicks} [::plotchart::determineScale $min $max] break
# Test:
catch {console show}
catch {wm withdraw .}
foreach x {7 11 22 33 44 77} {
puts "$x nice_number: [nice_number $x]"
puts "$x Roughly : [Roughly $x] \n"
}HJG Test added.

