Skip to content

Commit 53649d3

Browse files
authored
Add Fraction Math in Tcl (#5060)
1 parent 88cdba3 commit 53649d3

File tree

1 file changed

+107
-0
lines changed

1 file changed

+107
-0
lines changed

archive/t/tcl/fraction-math.tcl

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
oo::class create Fraction {
2+
variable numer denom
3+
4+
constructor {fractionStr} {
5+
if {[regexp {^\s*(-?\d+)\s*/\s*(\d+)\s*$} $fractionStr -> n d]} {
6+
# NUM/DEN format
7+
} elseif {[regexp {^\s*(-?\d+)$} $fractionStr -> n]} {
8+
# Integer format
9+
set n $n
10+
set d 1
11+
} else {
12+
error "Invalid fraction: $fractionStr"
13+
}
14+
15+
set numer [expr {$n}]
16+
set denom [expr {$d}]
17+
18+
if {$denom == 0} { error "Denominator cannot be zero" }
19+
20+
set a [expr {abs($numer)}]
21+
set b [expr {abs($denom)}]
22+
while {$b != 0} {
23+
set t $b
24+
set b [expr {$a % $b}]
25+
set a $t
26+
}
27+
set g $a
28+
29+
set numer [expr {($numer / $g) * ($denom < 0 ? -1 : 1)}]
30+
set denom [expr {abs($denom) / $g}]
31+
}
32+
33+
method numer {} {return $numer}
34+
method denom {} {return $denom}
35+
36+
method print {} { return ($denom == 1) ? "$numer" : "$numer/$denom" }
37+
38+
method _binOp {other op} {
39+
set on [$other numer]
40+
set od [$other denom]
41+
switch -- $op {
42+
+ {set n [expr {$numer * $od + $on * $denom}]; set d [expr {$denom * $od}]}
43+
- {set n [expr {$numer * $od - $on * $denom}]; set d [expr {$denom * $od}]}
44+
* {set n [expr {$numer * $on}]; set d [expr {$denom * $od}]}
45+
/ {
46+
if {$on == 0} { error "Division by zero" }
47+
set n [expr {$numer * $od}]
48+
set d [expr {$denom * $on}]
49+
}
50+
}
51+
return [Fraction new "$n/$d"]
52+
}
53+
54+
method add {other} {return [my _binOp $other +]}
55+
method sub {other} {return [my _binOp $other -]}
56+
method mult {other} {return [my _binOp $other *]}
57+
method div {other} {return [my _binOp $other /]}
58+
59+
method _cross {other} {
60+
set on [$other numer]
61+
set od [$other denom]
62+
return [expr {$numer * $od - $on * $denom}]
63+
}
64+
65+
method eq {other} {return [expr {[my _cross $other] == 0}]}
66+
method ne {other} {return [expr {[my _cross $other] != 0}]}
67+
method lt {other} {return [expr {[my _cross $other] < 0}]}
68+
method le {other} {return [expr {[my _cross $other] <= 0}]}
69+
method gt {other} {return [expr {[my _cross $other] > 0}]}
70+
method ge {other} {return [expr {[my _cross $other] >= 0}]}
71+
}
72+
73+
if {[llength $argv] != 3} {
74+
puts "Usage: ./fraction-math operand1 operator operand2"
75+
exit 1
76+
}
77+
78+
set op1 [string trim [lindex $argv 0]]
79+
set oper [string trim [lindex $argv 1]]
80+
set op2 [string trim [lindex $argv 2]]
81+
82+
if {[catch {set f1 [Fraction new $op1]} err]} {
83+
puts "Error: $err"
84+
exit 1
85+
}
86+
if {[catch {set f2 [Fraction new $op2]} err]} {
87+
puts "Error: $err"
88+
exit 1
89+
}
90+
91+
set opMap [dict create \
92+
+ add - sub * mult / div \
93+
== eq != ne > gt < lt >= ge <= le]
94+
95+
if {![dict exists $opMap $oper]} {
96+
puts "Unknown operator: $oper"
97+
exit 1
98+
}
99+
100+
set result [$f1 [dict get $opMap $oper] $f2]
101+
102+
if {[lsearch -exact {+ - * /} $oper] != -1} {
103+
puts [$result print]
104+
} else {
105+
puts $result
106+
}
107+

0 commit comments

Comments
 (0)