function Chars(const ACount: Integer; const AChar: Char = ' '): string;
var
i: Integer;
begin
Result := '';
if ACount < 1 then Exit;
SetLength(Result, ACount);
for i := 1 to ACount do
Result[i] := AChar;
end;
function GetMaxCommDivisor(AMin, AMax: Integer): Integer;
var
Mid: Integer;
begin
if AMax <= AMin then
begin
Mid := AMax;
AMax := AMin;
AMin := Mid;
end;
repeat
Mid := AMax mod AMin;
AMax := AMin;
AMin := Mid;
until Mid = 0;
Result := AMax;
end;
function FloatToFrac(const AValue: Extended; ADecDigit: Integer): string;
const
s_FmtFloat = '0.';
var
Idx, Numerator, Denominator, MaxCommDiv: Integer;
sFormat, sValue, sIntPart, sFracPart: string;
begin
if ADecDigit <= 0 then
begin
ADecDigit := 2;
end else begin
if ADecDigit > 9 then
ADecDigit := 9;
end;
sFormat := s_FmtFloat + Chars(ADecDigit, '0');
sValue := FormatFloat(sFormat, Abs(AValue));
Idx := Pos('.', sValue);
// Integer value.
if Idx = 0 then
begin
Result := sValue;
Exit;
end;
// Floating point value.
sIntPart := Copy(sValue, 1, Idx-1);
sFracPart := Copy(sValue, Idx+1, ADecDigit);
Numerator := StrToInt(sFracPart);
if Numerator = 0 then
begin
Result := sIntPart;
end else begin
Denominator := StrToInt('1' + Chars(ADecDigit, '0'));
MaxCommDiv := GetMaxCommDivisor(Numerator, Denominator);
Numerator := Numerator div MaxCommDiv;
Denominator := Denominator div MaxCommDiv;
if sIntPart > '0' then
begin
Result := Format('%s-%d/%d', [sIntPart, Numerator, Denominator]);
end else begin
Result := Format('%d/%d', [Numerator, Denominator]);
end;
end;
if AValue < 0 then
begin
Result := '(' + Result + ')';
end;
end;