我编写了这个函数,将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
是双精度数。我正在使用拉撒路,我总是有这个错误:
我确信上面的代码没有逻辑上的麻烦,因为它来自我上周在项目中实现的Java类(code)。
我错过了什么?我的Delphi项目的完整代码可以找到here。
答案 0 :(得分:3)
错误肯定会在这里发生:
y := 1/(y-a);
当y-a
评估为0
时,这将导致除以零错误。将0
传递给函数时会发生这种情况。
或者当您评估h1/k1
时,k1
的值为零。同样,这是一个浮点异常。
即使你陷入这些条件,我也无法让这个函数返回对我来说似乎有点敏感的东西。因此,一旦您修复了异常条件,您就可以继续工作了。
我确信你可以在调试器中解决这个问题,即使你不能通过阅读代码来解决这个问题。调试器会告诉你哪一行产生了错误,然后只是检查表达式中操作数的值。
答案 1 :(得分:1)
对于它的价值,你的重复循环是错误的方式。您正在用do/while
替换java repeat/until
- 条件必须反转才能生效。
为了避免被零除,只需检查并中断循环。这样可以避免崩溃,但我还没有确认它会始终产生正确的答案,尽管它适用于0.25
或0.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 >