Skip to content

Commit 5a31886

Browse files
authored
Add Fraction Math in Pascal (TheRenegadeCoder#4832)
1 parent e4046a4 commit 5a31886

File tree

1 file changed

+199
-0
lines changed

1 file changed

+199
-0
lines changed

archive/p/pascal/fraction_math.pas

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
program FractionMath;
2+
3+
{$mode objfpc}{$H+}{$modeswitch advancedrecords}
4+
5+
uses
6+
Math,
7+
SysUtils;
8+
9+
type
10+
11+
{ TFraction }
12+
13+
TFraction = record
14+
Numerator, Denominator: int64;
15+
16+
procedure Reduce;
17+
function ToString: string;
18+
class operator +(const A, B: TFraction): TFraction;
19+
class operator -(const A, B: TFraction): TFraction;
20+
class operator *(const A, B: TFraction): TFraction;
21+
class operator /(const A, B: TFraction): TFraction;
22+
class operator =(const A, B: TFraction): boolean;
23+
class operator <>(const A, B: TFraction): boolean;
24+
class operator <(const A, B: TFraction): boolean;
25+
class operator <=(const A, B: TFraction): boolean;
26+
class operator >(const A, B: TFraction): boolean;
27+
class operator >=(const A, B: TFraction): boolean;
28+
end;
29+
30+
procedure TFraction.Reduce; inline;
31+
var
32+
Divisor, GcdA, GcdB, Temp: int64;
33+
begin
34+
if Denominator = 0 then
35+
raise Exception.Create('Denominator cannot be zero');
36+
37+
if Numerator = 0 then
38+
begin
39+
Denominator := 1;
40+
Exit;
41+
end;
42+
43+
if Denominator < 0 then
44+
begin
45+
Denominator := -Denominator;
46+
Numerator := -Numerator;
47+
end;
48+
49+
GcdA := Abs(Numerator);
50+
GcdB := Denominator;
51+
52+
while GcdB <> 0 do
53+
begin
54+
Temp := GcdB;
55+
GcdB := GcdA mod GcdB;
56+
GcdA := Temp;
57+
end;
58+
59+
Divisor := GcdA;
60+
61+
// If the GCD is not 1, then simplify the top and the bottom.
62+
if Divisor > 1 then
63+
begin
64+
Numerator := Numerator div Divisor;
65+
Denominator := Denominator div Divisor;
66+
end;
67+
end;
68+
69+
function TFraction.ToString: string;
70+
begin
71+
Result := Format('%d/%d', [Numerator, Denominator]);
72+
end;
73+
74+
class operator TFraction.+(const A, B: TFraction): TFraction;
75+
begin
76+
Result.Numerator := A.Numerator * B.Denominator + B.Numerator * A.Denominator;
77+
Result.Denominator := A.Denominator * B.Denominator;
78+
Result.Reduce;
79+
end;
80+
81+
class operator TFraction.-(const A, B: TFraction): TFraction;
82+
begin
83+
Result.Numerator := A.Numerator * B.Denominator - B.Numerator * A.Denominator;
84+
Result.Denominator := A.Denominator * B.Denominator;
85+
Result.Reduce;
86+
end;
87+
88+
class operator TFraction.*(const A, B: TFraction): TFraction;
89+
begin
90+
Result.Numerator := A.Numerator * B.Numerator;
91+
Result.Denominator := A.Denominator * B.Denominator;
92+
Result.Reduce;
93+
end;
94+
95+
class operator TFraction./(const A, B: TFraction): TFraction;
96+
begin
97+
if B.Numerator = 0 then
98+
raise Exception.Create('Division by zero fraction');
99+
100+
Result.Numerator := A.Numerator * B.Denominator;
101+
Result.Denominator := A.Denominator * B.Numerator;
102+
Result.Reduce;
103+
end;
104+
105+
class operator TFraction.=(const A, B: TFraction): boolean;
106+
begin
107+
Result := A.Numerator * B.Denominator = B.Numerator * A.Denominator;
108+
end;
109+
110+
class operator TFraction.<>(const A, B: TFraction): boolean;
111+
begin
112+
Result := not (A = B);
113+
end;
114+
115+
class operator TFraction.<(const A, B: TFraction): boolean;
116+
begin
117+
Result := A.Numerator * B.Denominator < B.Numerator * A.Denominator;
118+
end;
119+
120+
class operator TFraction.>=(const A, B: TFraction): boolean;
121+
begin
122+
Result := not (A < B);
123+
end;
124+
125+
class operator TFraction.>(const A, B: TFraction): boolean;
126+
begin
127+
Result := B < A;
128+
end;
129+
130+
class operator TFraction.<=(const A, B: TFraction): boolean;
131+
begin
132+
Result := not (B < A);
133+
end;
134+
135+
function ParseFraction(const S: string): TFraction;
136+
var
137+
Parts: TStringArray;
138+
begin
139+
Parts := S.Trim.Split(['/']);
140+
if Length(Parts) <> 2 then
141+
raise Exception.CreateFmt('Invalid fraction format "%s". Expected "num/den"', [S]);
142+
143+
if not TryStrToInt64(Parts[0].Trim, Result.Numerator) then
144+
raise Exception.Create('Invalid numerator');
145+
146+
if not TryStrToInt64(Parts[1].Trim, Result.Denominator) then
147+
raise Exception.Create('Invalid denominator');
148+
149+
if Result.Denominator = 0 then
150+
raise Exception.Create('Denominator cannot be zero');
151+
152+
Result.Reduce;
153+
end;
154+
155+
procedure ShowUsage;
156+
begin
157+
Writeln('Usage: ./fraction-math operand1 operator operand2');
158+
Halt(1);
159+
end;
160+
161+
function PerformOperation(const Left: TFraction; const Op: string;
162+
const Right: TFraction): string;
163+
begin
164+
case Op of
165+
'+': Result := (Left + Right).ToString;
166+
'-': Result := (Left - Right).ToString;
167+
'*': Result := (Left * Right).ToString;
168+
'/': Result := (Left / Right).ToString;
169+
'==': Result := BoolToStr(Left = Right, '1', '0');
170+
'!=': Result := BoolToStr(Left <> Right, '1', '0');
171+
'<': Result := BoolToStr(Left < Right, '1', '0');
172+
'<=': Result := BoolToStr(Left <= Right, '1', '0');
173+
'>': Result := BoolToStr(Left > Right, '1', '0');
174+
'>=': Result := BoolToStr(Left >= Right, '1', '0');
175+
else
176+
raise Exception.CreateFmt('Unknown operator: "%s"', [Op]);
177+
end;
178+
end;
179+
180+
181+
var
182+
Op: string;
183+
LeftOperand, RightOperand: TFraction;
184+
begin
185+
if ParamCount <> 3 then
186+
ShowUsage;
187+
188+
try
189+
LeftOperand := ParseFraction(ParamStr(1));
190+
Op := ParamStr(2).Trim;
191+
RightOperand := ParseFraction(ParamStr(3));
192+
193+
Writeln(PerformOperation(LeftOperand, &Op, RightOperand));
194+
except
195+
on E: Exception do
196+
ShowUsage;
197+
end;
198+
199+
end.

0 commit comments

Comments
 (0)