-1

I have written this function that converts a double to a fraction returning a string:

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; 

And then I call it in this way: Edit7.Text := getFraction(x); where the x is a double. I am using lazarus and I always have this error:

enter image description here

I am sure that the code above has not logic hassles because it becomes from a Java class that I have implemented last week in a project (code).

What am I missing? The full code of my Delphi project can be found here.

J...
  • 30,968
  • 6
  • 66
  • 143
Alberto Rossi
  • 1,800
  • 4
  • 36
  • 58
  • 1
    Could you please show the real code. This isn't it. It cannot compile. And then please show the input value that leads to this floating point error. Perhaps you are passing `0` to the function. Your function also doesn't seem very useful. It converts 0.5 into `0/1` for example. What you are attempting to do is probably next to impossible, FWIW. – David Heffernan Oct 01 '14 at 21:16
  • 3
    Described here in many ways, [How to convert floats to human-readable fractions?](http://stackoverflow.com/q/95727/576719). – LU RD Oct 01 '14 at 21:31
  • @LURD Thanks. Interesting. – David Heffernan Oct 02 '14 at 04:42

2 Answers2

3

The error will surely occur here:

y := 1/(y-a);

When y-a evaluates to 0 then this will result in a divide by zero error. That happens when you pass 0 to the function.

Or perhaps when you evaluate h1/k1 the value of k1 is zero. Again, that's a floating point exception.

Even when you trap those conditions, I cannot make the function return anything that seems remotely sensible to me. So, once you fix the exception condition then you'll have further work.

I'm sure that you could have worked this out in the debugger, even if you could not do so by reading the code. The debugger will tell you which line produced the error and then it is merely a matter of inspecting the value of the operands in the expression.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • Thanks for your suggestions, I'll try to work on it now. Anyway the Java version works perfectly, and a 0.5 becomes a 1/2 (which is correct). I must find out the problem here with Delphi – Alberto Rossi Oct 01 '14 at 21:25
1

For what it's worth, your repeat loop is the wrong way around. You're replacing a java do/while with repeat/until - the condition has to invert for this to work.

To avoid divide by zero, just check and break out of the loop. That will save the crash, but I haven't verified that it will always produce the right answer, although it does for previously deadly inputs like 0.25 or 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 >
J...
  • 30,968
  • 6
  • 66
  • 143