Unit ufraction;

{$MODE objfpc}{$H+}

Interface

Uses
  SysUtils;

Type

  TFraction = Record
    numerator: Int64; // Zähler
    denominator: Int64; // Nenner
  End;

  Operator := (i: Byte): Tfraction;
  Operator := (i: ShortInt): Tfraction;
  Operator := (i: Integer): Tfraction;
  Operator := (i: Int64): Tfraction;

  Operator := (f: TFraction): String;
  Operator := (f: TFraction): Single;
  Operator := (f: TFraction): Double;
  Operator := (f: TFraction): Extended;

  Operator - (a: TFraction): TFraction;
  Operator - (a, b: TFraction): TFraction;
  Operator + (a, b: TFraction): TFraction;
  Operator * (a, b: TFraction): TFraction;
  Operator / (a, b: TFraction): TFraction;

Function abs(v: TFraction): Tfraction; // Berechnet den Absolutwert
Function fraction(numerator, denominator: Int64): TFraction; // Konvertierung
Function shorten(v: TFraction): Tfraction; // Kürzen

Implementation

Function ggT(a, b: Int64): Int64;
Begin
  If a = 0 Then Begin
    Result := b;
  End
  Else Begin
    While b <> 0 Do Begin
      If a > b Then Begin
        a := a - b;
      End
      Else Begin
        b := b - a;
      End;
    End;
    Result := a;
  End;
End;

Operator := (i: Byte): Tfraction;
Begin
  result.numerator := i;
  result.denominator := 1;
End;

Operator := (i: ShortInt): Tfraction;
Begin
  result.numerator := i;
  result.denominator := 1;
End;

Operator := (i: Integer): Tfraction;
Begin
  result.numerator := i;
  result.denominator := 1;
End;

Operator := (i: Int64): Tfraction;
Begin
  result.numerator := i;
  result.denominator := 1;
End;

Operator := (f: TFraction): String;
Begin
  If f.denominator <> 0 Then
    result := floattostr(f.numerator / f.denominator)
  Else
    result := 'Error div 0';
End;

Operator := (f: TFraction): Single;
Begin
  If f.denominator <> 0 Then
    result := f.numerator / f.denominator
  Else
    result := 0;
End;

Operator := (f: TFraction): Double;
Begin
  If f.denominator <> 0 Then
    result := f.numerator / f.denominator
  Else
    result := 0;
End;

Operator := (f: TFraction): Extended;
Begin
  If f.denominator <> 0 Then
    result := f.numerator / f.denominator
  Else
    result := 0;
End;

Operator - (a: TFraction): TFraction;
Begin
  result := a;
  result.numerator := -result.numerator;
  result := shorten(result);
End;

Operator - (a, b: TFraction): TFraction;
Begin
  result.numerator := a.numerator * b.denominator - b.numerator * a.denominator;
  result.denominator := a.denominator * b.denominator;
  result := shorten(result);
End;

Operator + (a, b: TFraction): TFraction;
Begin
  result.numerator := a.numerator * b.denominator + b.numerator * a.denominator;
  result.denominator := a.denominator * b.denominator;
  result := shorten(result);
End;

Operator * (a, b: TFraction): TFraction;
Begin
  result.numerator := a.numerator * b.numerator;
  result.denominator := a.denominator * b.denominator;
  result := shorten(result);
End;

Operator / (a, b: TFraction): TFraction;
Begin
  result.numerator := a.numerator * b.denominator;
  result.denominator := a.denominator * b.numerator;
  result := shorten(result);
End;

Function abs(v: TFraction): Tfraction;
Begin
  result.numerator := system.abs(v.numerator);
  result.denominator := system.abs(v.denominator);
End;

Function fraction(numerator, denominator: Int64): TFraction;
Begin
  result.numerator := numerator;
  If denominator <> 0 Then
    result.denominator := denominator
  Else
    result.denominator := 1;
End;

Function shorten(v: TFraction): Tfraction;
Var
  i: Int64;
Begin
  If (v.numerator < 0) And (v.denominator < 0) Then Begin
    v := abs(v);
  End;
  i := ggT(system.abs(v.numerator), system.abs(v.denominator));
  If (i <> system.abs(v.numerator)) And (i <> system.abs(v.denominator)) And (i > 1) Then Begin
    result.numerator := v.numerator Div i;
    result.denominator := v.denominator Div i;
  End
  Else
    result := v;
End;

End.

