Delphi小数转换成分数函数

//=======================小数转分数======================================
function Fraction(decimal: double): string;
var
intNumerator, intDenominator, intNegative: integer; // 声明整数变量为长整数
dblFraction, dblDecimal, dblAccuracy, dblinteger: Double; // 声明浮点数为双精度
begin
dblDecimal := decimal; //取得目标小数
if trunc(decimal) = decimal then // 如果是整数,则直转
    result := floattostr(decimal)
else
begin
    if abs(decimal) > 1 then //如果小数大于1 如 10.24 ,进行拆解
    begin
      dblinteger := trunc(decimal); //取出整数部分
      dblDecimal := abs(frac(decimal)); //取出小数部分
    end
    else dblDecimal := decimal;

    dblAccuracy := 0.01; //设置精度
    intNumerator := 0; //初始分子为0
    intDenominator := 1; //初始分母为1
    intNegative := 1; //符号标记为正
    if dblDecimal < 0 then intNegative := -1; //如果目标为负,设置负标志位
    dblFraction := 0; //设置分数值为 0/1
    while Abs(dblFraction - dblDecimal) > dblAccuracy do //如果当前没有达到精度要求就继续循环
    begin
      if Abs(dblFraction) > Abs(dblDecimal) then //如果我们的分数大于目标
        intDenominator := intDenominator + 1 //增加分母
      else //否则
        intNumerator := intNumerator + intNegative; //增加分子
      dblFraction := intNumerator / intDenominator; //计算新的分数
    end;
   // edit2.Text := inttostr(intNumerator) + '/' + inttostr(intDenominator);
    if abs(decimal) > 1 then //如果小数大于1 如 10.24 ,进行拆解
      result := floattostr(dblinteger) + ' ' + inttostr(intNumerator) + '/' + inttostr(intDenominator)
    else
      result := inttostr(intNumerator) + '/' + inttostr(intDenominator);
end;
end;

procedure TForm1.Button10Click(Sender: TObject);
begin
showmessage(Fraction(8/9));
end;

修改后化成假分数:

function Fraction(decimal: double): string;
var
intNumerator, intDenominator, intNegative: integer; // 声明整数变量为长整数
dblFraction, dblDecimal, dblAccuracy, dblinteger: Double; // 声明浮点数为双精度
temp:string;
begin
dblDecimal := decimal; //取得目标小数
if trunc(decimal) = decimal then // 如果是整数,则直转
    result := floattostr(decimal)
else
begin
    if abs(decimal) > 1 then //如果小数大于1 如 10.24 ,进行拆解
    begin
      dblinteger := trunc(decimal); //取出整数部分
      dblDecimal := abs(frac(decimal)); //取出小数部分
    end
    else dblDecimal := decimal;

    dblAccuracy := 0.01; //设置精度
    intNumerator := 0; //初始分子为0
    intDenominator := 1; //初始分母为1
    intNegative := 1; //符号标记为正
    if dblDecimal < 0 then intNegative := -1; //如果目标为负,设置负标志位
    dblFraction := 0; //设置分数值为 0/1
    while Abs(dblFraction - dblDecimal) > dblAccuracy do //如果当前没有达到精度要求就继续循环
    begin
      if Abs(dblFraction) > Abs(dblDecimal) then //如果我们的分数大于目标
        intDenominator := intDenominator + 1 //增加分母
      else //否则
        intNumerator := intNumerator + intNegative; //增加分子
      dblFraction := intNumerator / intDenominator; //计算新的分数
    end;
   // edit2.Text := inttostr(intNumerator) + '/' + inttostr(intDenominator);
    if abs(decimal) > 1 then //如果小数大于1 如 10.24 ,进行拆解
     //结果:dblinteger为整数部分, intNumerator为分子,intDenominator为分母
     begin
     if dblinteger<0 then
       begin dblinteger := -dblinteger;
       temp := floattostr(dblinteger*intDenominator+intNumerator) + '/' + inttostr(intDenominator);
       //result := floattostr(dblinteger) + '又' + inttostr(intNumerator) + '/' + inttostr(intDenominator)
       result := '-'+temp;
       end else
       begin
       temp := floattostr(dblinteger*intDenominator+intNumerator) + '/' + inttostr(intDenominator);
       result :=temp;
       end;
     end
    else
      result := inttostr(intNumerator) + '/' + inttostr(intDenominator);
end;
end;

这个算法的根本原理是:一个分数对应一条直线的斜率。用数学语言描述就是:一条直线的斜率是无穷大(垂直于X轴)或者是(Y2-Y1) / (X2-X1),我们要做的就是找到2个整数,在指定的精度范围内接近这个斜率。对于正数来说,我们设置分子为0,分母为1,然后比较这个分数同给定的十进制数。如果我们的分数太小了(比如,我们选择的点在直线的下面),我们就加大分子的值直到这个分数太大(比如,这个点在直线的上方),之后我们在增加分母的大小直到这个点在直线下方。
如果我们的最终目标是无理数(无限不循环小数),这个算法将一直继续,增加分子和分母,直到最终结果在指定的精度上。