2006. november 2., csütörtök
How to convert decimal numbers to fractions
Problem/Question/Abstract:
I'm looking for a function that I can pass in a decimal and return a fraction.
Answer:
Solve 1:
The "Denominators" parameter is an array of potential denominators that would be acceptable. For example, to get a fractional inch dimension with a power of 2 denominator, you'd pass [2, 4, 8, 16, 32] for that parameter, and the function will figure out which potential denominator will work best.
function ConvertFloatToFraction(const Value: Double;
const Denominators: array of Integer): string;
var
Index: Integer;
TempDelta: Double;
MinDelta: Double;
TempNumerator: Integer;
FracValue: Double;
Numerator: Integer;
Denominator: Integer;
IntValue: Integer;
begin
IntValue := Trunc(Value);
FracValue := Abs(Frac(Value));
MinDelta := 0;
Numerator := 0;
Denominator := 0;
for Index := 0 to High(Denominators) do
begin
TempNumerator := Round(FracValue * Denominators[Index]);
TempDelta := Abs(FracValue - (TempNumerator / Denominators[Index]));
if ((Index = 0) or (TempDelta < MinDelta)) then
begin
MinDelta := TempDelta;
Numerator := TempNumerator;
Denominator := Denominators[Index];
end;
end;
if (Numerator = Denominator) then
begin
IntValue := IntValue + Sign(IntValue);
Numerator := 0;
end;
Result := '';
if ((IntValue <> 0) or (Numerator = 0)) then
Result := IntToStr(IntValue);
if ((IntValue <> 0) and (Numerator <> 0)) then
Result := Result + ' ';
if (Numerator <> 0) then
Result := Result + IntToStr(Numerator) + '/' + IntToStr(Denominator);
end;
Solve 2:
This function takes the number to convert, the fraction scale you want returned such as 8 for eighths or 10 for tenths, etc. and a boolean to tell it to round up or down the nearest fraction. It returns a string with the integer portion, a space and then the fraction portion. It will also reduce the fraction to the smallest common denominator. You can use the ErrorFactor variable to adjust the percentage of when to consider a number close enough to the next level to be close enough. I use 4 percent of the fractional scale value.
function ToFraction(num: double; scale: integer; RoundUp: boolean): string;
{Function to find greatest common denominator}
function GCD(A, B: integer): integer;
begin
if (B mod A) = 0 then
result := A
else if (B mod A) = 1 then
result := 1
else
result := GCD((B mod A), A);
end;
var
x, y: integer;
ScaleFrac,
NumFrac,
ErrorFactor: double;
begin
ScaleFrac := 1 / scale;
NumFrac := Frac(Num);
ErrorFactor := ScaleFrac * 0.04; {error factor of 4 percent}
x := 0;
while (((x + 1) * ScaleFrac) < (NumFrac + ErrorFactor)) do
inc(x);
if RoundUp then
if (((((x + 1) * ScaleFrac) - NumFrac) / 2) > (ScaleFrac / 2)) then
inc(x);
if (x = 0) then {no fraction, just the integer portion}
begin
result := IntToStr(Trunc(Num))
end
else
begin {reduce the fraction as much as possible}
y := GCD(x, scale);
while (y <> 1) do
begin
x := x div y;
scale := scale div y;
y := GCD(x, scale);
end;
result := IntToStr(Trunc(Num)) + ' ' + IntToStr(x) + '/' + IntToStr(scale);
end;
end;
Feliratkozás:
Megjegyzések küldése (Atom)
Nincsenek megjegyzések:
Megjegyzés küldése