module Math
Rational approximation to given real number.
Public Class Methods
find_fracs(p1, p2)
click to toggle source
static VALUE find_fracs(VALUE mod, VALUE rv, VALUE dv) { N_TYPE m[2][2], ai, maxden = R2N(rb_Integer(dv)); double startx, x = RFLOAT_VALUE(rb_Float(rv)); int sign = 1; if (maxden <= 0) rb_raise(rb_eArgError, "maximum denominator should be > 0"); if (x < 0) { sign = -1; x = -x; } startx = x; /* initialize matrix */ m[0][0] = m[1][1] = 1; m[0][1] = m[1][0] = 0; /* loop finding terms until denom gets too big */ while (m[1][0] * ( ai = (N_TYPE)x ) + m[1][1] <= maxden) { N_TYPE t; t = m[0][0] * ai + m[0][1]; m[0][1] = m[0][0]; m[0][0] = t; t = m[1][0] * ai + m[1][1]; m[1][1] = m[1][0]; m[1][0] = t; if(x==(double)ai) break; // AF: division by zero x = 1/(x - (double) ai); if(x>(double)0x7FFFFFFF) break; // AF: representation failure } { /* now remaining x is between 0 and 1/ai */ /* approx as either 0 or 1/m where m is max that will fit in maxden */ /* first try zero */ VALUE num1, den1, err1, num2, den2, err2; num1 = N2R(sign*m[0][0]); den1 = N2R(m[1][0]); err1 = rb_float_new(startx - ((double) m[0][0] / (double) m[1][0])); /* now try other possibility */ ai = (maxden - m[1][1]) / m[1][0]; m[0][0] = m[0][0] * ai + m[0][1]; m[1][0] = m[1][0] * ai + m[1][1]; num2 = N2R(sign*m[0][0]); den2 = N2R(m[1][0]); err2 = rb_float_new(startx - ((double) m[0][0] / (double) m[1][0])); return rb_ary_new3(6, num1, den1, err1, num2, den2, err2); } }
frac(float, maxden)
click to toggle source
# File lib/frac.rb, line 9 def frac(float, maxden) arr = find_fracs(float, maxden) arr[2].abs > arr[5].abs ? Rational(arr[3], arr[4]) : Rational(arr[0], arr[1]) end