Posted to tcl by kbk at Fri Jul 04 17:18:54 GMT 2008view pretty
namespace path {::tcl::mathop ::tcl::mathfunc}
# Take a decimal number and convert it to a rational. Return a two
# element list of numerator and denominator
proc to-rational {n} {
if {![regexp {^([-+]?[0-9]*)(?:[.]([0-9]*))?$} $n -> integer fraction]} {
return -code error "$n is not a number"
}
set denom [** 10 [string length $fraction]]
# TODO - Reduce to lowest terms
return [list $integer$fraction $denom]
}
puts [to-rational 6.25]
# Take a decimal number representing a percentage and convert it to a
# rational. Return a two element list of numerator and denominator
proc percent {n} {
lassign [to-rational $n] num denom
# TODO - Reduce to lowest terms
return [list $num [* 100 $denom]]
}
puts [percent 6.25]
# Multiply two rationals
proc rat-times {m n} {
set result {}
foreach x $m y $n {
lappend result [* $x $y]
}
return $result
}
# What is 6.25% of 19.45?
set val [rat-times [percent 6.25] [to-rational 19.45]]
puts $val
# Take the integer part of a rational, with banker's rounding
proc rat-int {n} {
lassign $n num denom
set ipart [/ $num $denom]
set fpart [% $num $denom]
if {$fpart < 0} {
incr ipart -1
incr fpart $denom
}
if {2 * $fpart < $denom} {
return $ipart
} elseif {2 * $fpart > $denom} {
return [+ $ipart 1]
} else {
return [+ $ipart [% $ipart 2]]
}
}
# How many pennies is 6.25% times 19.45?
set resultCents [rat-int [rat-times {100 1} $val]]
puts $resultCents
# Convert an integer count of pennies to standard notation
proc penniesToDollars {cents} {
# TODO - Doesn't handle + and - signs correctly
if {[string length $cents] < 3} {
set cents [string repeat [- 3 [string length $cents]] 0]$cents
}
return [string range $cents 0 end-2].[string range $cents end-1 end]
}
puts \$[penniesToDollars $resultCents]