When the module was ready, I saw that a year ago, participants in the English-language freepascal forum developed a similar, albeit collectively, weighed down with a mass of functions and various implementations of the same. Well, we will consider made by a kind of import substitution.
TFraction = record Numerator: longint; Denumerator: longint; function Create(ANum, ADenum: longint): TFraction; function toStr: string; function toFloat: extended; end;
Do not forget to include the necessary compiler directive - {$ MODESWITCH ADVANCEDRECORDS}
// procedure SetEqualDenum(var ALeftFr, ARightFr: TFraction); // - function ExpandFraction(AFraction: TFraction; Factor: longint): TFraction; // function gcd(ALeftDenum, ARightDenum: longint): longint; // function lcm(ALeftDenum, ARightDenum: longint): longint; // - , toGCD function CollapseFraction(AFraction: TFraction; Divider: longint = toGCD): TFraction; // function CompareFractions(ALeftFr, ARightFr: TFraction): TfrCompareResult; // , function ReverseFraction(AFraction: TFraction): TFraction;
// operator +(ALeftFr, ARightFr: TFraction) r: TFraction; // operator +(ALeftFr: TFraction; const Term: longint) r: TFraction; // operator -(ALeftFr, ARightFr: TFraction) r: TFraction; // operator -(ALeftFr: TFraction; const Sub: longint) r: TFraction; // operator * (ALeftFr, ARightFr: TFraction) r: TFraction; // operator * (AFraction: TFraction; const Multiplier: longint) r: TFraction; operator * (const Multiplier: longint; AFraction: TFraction) r: TFraction; // operator / (ALeftFr, ARightFr: TFraction) r: TFraction; // operator / (AFraction: TFraction; const Divider: longint) r: TFraction; // operator = (ALeftFr, ARightFr: TFraction) r: boolean; // , operator > (ALeftFr, ARightFr: TFraction) r: boolean; // , operator < (ALeftFr, ARightFr: TFraction) r: boolean; // ( = 1) operator := (const AIntegerPart: longint) r: TFraction; // / operator := (const AStringFr: string) r: TFraction;
Unfortunately, in freepascal it is impossible to transfer as an assigned value an enumeration of integers (dictionary, set, call it what you like, the meaning is that it is impossible: A: = (1,2); or so B: = [1,2] ), therefore, the initiation of a fraction goes through a constructor function or a string value, although nothing prevents you from simply setting values ​​to two fields, but I wanted to make it as simple as possible.
operator+(ALeftFr, ARightFr: TFraction)r: TFraction; begin SetEqualDenum(ALeftFr, ARightFr); r.Numerator := ALeftFr.Numerator + ARightFr.Numerator; r.Denumerator := ALeftFr.Denumerator; r := CollapseFraction(r, toGCD); end; ... operator/(ALeftFr, ARightFr: TFraction)r: TFraction; begin r := ALeftFr * ReverseFraction(ARightFr); end; ... operator:=(const AStringFr: string)r: TFraction; var i: integer; begin i := PosEx(char(SolidorSym), AStringFr); if not TryStrToInt(LeftStr(AStringFr, i - 1), r.Numerator) then raise Exception.Create('Numerator is not integer!'); if not TryStrToInt(RightStr(AStringFr, Length(AStringFr) - i), r.Denumerator) then raise Exception.Create('Denumerator is not integer!'); end; ... operator=(ALeftFr, ARightFr: TFraction)r: boolean; begin Result := CompareFractions(ALeftFr, ARightFr) = crEqual; end; operator>(ALeftFr, ARightFr: TFraction)r: boolean; begin Result := CompareFractions(ALeftFr, ARightFr) = crLeft; end; operator<(ALeftFr, ARightFr: TFraction)r: boolean; begin Result := CompareFractions(ALeftFr, ARightFr) = crRight; end;
function gcd(ALeftDenum, ARightDenum: longint): longint; begin if ARightDenum = 0 then Result := abs(ALeftDenum) else Result := abs(gcd(ARightDenum, ALeftDenum mod ARightDenum)); end;
function lcm(ALeftDenum, ARightDenum: longint): longint; begin Result := abs(ALeftDenum * ARightDenum) div gcd(ALeftDenum, ARightDenum); end;
procedure SetEqualDenum(var ALeftFr, ARightFr: TFraction); var tDenum: longint; begin if ALeftFr.Denumerator = ARightFr.Denumerator then exit; tDenum := lcm(ALeftFr.Denumerator, ARightFr.Denumerator); ALeftFr := ExpandFraction(ALeftFr, tDenum div ALeftFr.Denumerator); ARightFr := ExpandFraction(ARightFr, tDenum div ARightFr.Denumerator); end;
Fr1, Fr2: TFraction; ... Fr1 := 12; // ( 12/1) Fr2 := '3/5'; // ( ) // Fr3 := TFraction.Create(22,7); // 22/7
Fr3 := Fr1+ Fr2; Fr3 := Fr1 * Fr2; Fr2 := Fr1 - 1; Fr2 := Fr1 / 3; Fr3 := Fr1 / Fr2; if Fr1 > Fr2 …
Fr1 += Fr2; Fr2 -= 1; Fr3 *= '1/2';
if Fr1 > '2/3' ... while Fr2 < 1 ...
Source: https://habr.com/ru/post/327450/
All Articles