package provide packedDecimal 0.1 namespace eval packedDecimal { namespace export add subtract multiply divide setDecimals variable decimals 2 variable formatString {%d.%2.2d} variable carry 100 } proc packedDecimal::add {a b} { variable decimals variable formatString scan $a %d.%d a1 a2 scan $b %d.%d b1 b2 incr a2 $b2 if {[string length $a2] > $decimals} then { incr a1 1 set a2 [string range $a2 1 end] } incr a1 $b1 return [format $formatString $a1 $a2] } proc packedDecimal::subtract {a b} { variable decimals variable formatString variable carry scan $a %d.%d a1 a2 scan $b %d.%d b1 b2 incr a2 -$b2 if {$a2 < 0} then { incr b1 1 set a2 [expr {$carry + $a2}] } incr a1 -$b1 return [format $formatString $a1 $a2] } # This is not really right yet! proc packedDecimal::roundingRule {a b} { variable carry while {$b >= $carry/2} { incr a 1 incr b -$carry } return [list $a $b] } # Does not handle negative values - DKF proc packedDecimal::multiply {a b} { variable decimals variable formatString variable carry scan $a %u.%u a1 a2 scan $b %u.%u b1 b2 set c1 [expr {$a1*$b1}] set c2 [expr {$a1*$b2 + $b1*$a2}] set c3 [expr {$a2*$b2}] foreach {c2 c3} [roundingRule $c2 $c3] {break} foreach {c1 c2} [roundingRule $c1 $c2] {break} if {$c2 < 0} { incr c1 -1 incr c2 $carry } return [format $formatString $c1 $c2] } proc packedDecimal::divide {a b} { variable decimals variable formatString return -code error {Sorry, Divide is not yet implemented!} } proc packedDecimal::setDecimals {a} { variable decimals variable formatString variable carry 100 set formatString [format {%%d.%%%d.%dd} $a $a] set decimals $a set carry [format "1%${a}.${a}d" 0] return; } proc packedDecimal::getDecimals {} { variable decimals return $decimals }
AM A FAQ that deals with decimal arithmetic can be found at [1]. There is also a formal specification available (and an implementation in C, with a "renewable" licence) [2].
beernutmark I have worked up a Decimal Arithmetic Package for tcl 8.5
Sarnold I have been doing some Decimal arithmetic with bignums.
Gerald Lester