从双倍得到分数

时间:2014-10-01 21:07:14

标签: delphi lazarus

我编写了这个函数,将double转换为返回字符串的小数:

function getFraction(x: double):string;
var h1, h2, k1, k2, y, a, aux : double;
begin

  //Setup the values
  h1 := 1;
  h2 := 0;
  k1 := 0;
  k2 := 1;
  y := x;

  //Generates the fraction
  repeat
   begin
    a := floor(y);
    aux := h1;
    h1 := a*h1+h2;
    h2 := aux;
    aux := k1;
    k1 := a*k1+k2;
    k2 := aux;
    y := 1/(y-a) ;
   end;
   until ( abs(x-h1/k1) > x*0.000001);

  //Output
  Result := FloatToStr(h1) + '/' + FloatToStr(k1);
end; 

然后我用这种方式调用它:Edit7.Text := getFraction(x);其中x是双精度数。我正在使用拉撒路,我总是有这个错误:

enter image description here

我确信上面的代码没有逻辑上的麻烦,因为它来自我上周在项目中实现的Java类(code)。

我错过了什么?我的Delphi项目的完整代码可以找到here

2 个答案:

答案 0 :(得分:3)

错误肯定会在这里发生:

y := 1/(y-a);

y-a评估为0时,这将导致除以零错误。将0传递给函数时会发生这种情况。

或者当您评估h1/k1时,k1的值为零。同样,这是一个浮点异常。

即使你陷入这些条件,我也无法让这个函数返回对我来说似乎有点敏感的东西。因此,一旦您修复了异常条件,您就可以继续工作了。

我确信你可以在调试器中解决这个问题,即使你不能通过阅读代码来解决这个问题。调试器会告诉你哪一行产生了错误,然后只是检查表达式中操作数的值。

答案 1 :(得分:1)

对于它的价值,你的重复循环是错误的方式。您正在用do/while替换java repeat/until - 条件必须反转才能生效。

为了避免被零除,只需检查并中断循环。这样可以避免崩溃,但我还没有确认它会始终产生正确的答案,尽管它适用于0.250.5以前的致命输入。

  repeat
    begin
      a := floor(y);
      aux := h1;
      h1 := a * h1 + h2;
      h2 := aux;
      aux := k1;
      k1 := a * k1 + k2;
      k2 := aux;
      if (y - a = 0) or (k1 = 0) then break;  //!!
      y := 1 / (y - a) ;
    end;
  until (Abs(x - h1 / k1) <= x * 0.000001); // Here <= instead of >