program DecimalToRational;
{$mode objfpc}{$H+}
{
convertDecimalToRational(s, num, den)
-------------------------------------
Converts a decimal number (given as a string) into a rational p/q.
Why parse the string?
• Free Pascal has no built‑in rational type.
• Floating‑point types cannot preserve exact decimal digits.
• Parsing the string ensures perfect accuracy.
Strategy:
1. Look for a decimal point.
2. If none → integer → numerator = n, denominator = 1.
3. Otherwise:
Example: "12.345"
integer part = 12
fractional part = 345
digits = 3
numerator = integer_part * 10^digits + fractional_part
denominator = 10^digits
4. Reduce the fraction using gcd (Euclid’s algorithm).
}
uses
SysUtils;
function gcd(a, b: Int64): Int64;
var
t: Int64;
begin
while b <> 0 do
begin
t := b;
b := a mod b;
a := t;
end;
Result := a;
end;
procedure convertDecimalToRational(const s: string; out num, den: Int64);
var
dotPos: Integer;
intPart, fracPart: string;
integerValue, fractionalValue: Int64;
digits, i: Integer;
begin
dotPos := Pos('.', s);
if dotPos = 0 then
begin
{ No decimal point → integer }
num := StrToInt64(s);
den := 1;
Exit;
end;
{ Split into integer and fractional parts }
intPart := Copy(s, 1, dotPos - 1);
fracPart := Copy(s, dotPos + 1, Length(s) - dotPos);
integerValue := StrToInt64(intPart);
fractionalValue := StrToInt64(fracPart);
digits := Length(fracPart);
{ Build denominator = 10^digits }
den := 1;
for i := 1 to digits do
den := den * 10;
{ Build numerator }
num := integerValue * den + fractionalValue;
{ Reduce fraction }
i := gcd(num, den);
num := num div i;
den := den div i;
end;
var
values: array[1..8] of string = (
'3.5', '12.75', '0.125', '100.001',
'7', '42.0', '0.333', '5.2'
);
num, den: Int64;
i: Integer;
begin
for i := 1 to Length(values) do
begin
convertDecimalToRational(values[i], num, den);
WriteLn(values[i], ' -> ', num, '/', den);
end;
end.
{
run:
3.5 -> 7/2
12.75 -> 51/4
0.125 -> 1/8
100.001 -> 100001/1000
7 -> 7/1
42.0 -> 42/1
0.333 -> 333/1000
5.2 -> 26/5
}