Posted to tcl by kbk at Fri Jul 04 17:18:54 GMT 2008view raw
- 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]