# another fine solution by misof # variables x and y have to be set # (x / y) is the exact fraction we want to approximate, y is a power of 10 # e.g. for the input 0.33456 set # x = 33456 # y = 100000 # # we seek the first fraction that falls into the interval < (10x-5)/10y , (10x+5)/10y ) # fraction comparison define less(a,b,c,d) { return (a*d < b*c); } # check whether c/d approximates a/b well define matches(a,b,c,d) { if (less(c,d,10*a-5,10*b)) return 0; if (less(c,d,10*a+5,10*b)) return 1; return 0; } # max() will come in handy define max(a,b) { if (a>b) return a; return b; } # set initial bounds for the search a = 0 b = 1 c = 1 d = 1 while (1) { # compute the number of successive steps to one side, do them all at once if (bd) { u = (a*y - b*x); v = (d*x - c*y); if (u<0) { u=-u; v=-v; } k = 1; l = (u-1)/v; if (l==0) l=1; e = k*a + l*c; f = k*b + l*d; } if (b==d) { e=a+c; f=b+d; k=1; l=1; } # if we hit the bull's eye, get the result if (matches(x,y,e,f)) { # we could've skipped the best solution # now we find it using binary search on the number of steps m=0; n=max(k,l); while (m+1 < n) { o = (m+n)/2 p = k-o; q = l-o; if (p<1) p=1; if (q<1) q=1; e = p*a + q*c; f = p*b + q*d; if (matches(x,y,e,f)) { m=o; } else { n=o; } } # compute the best result o = m; p = k-o; q = l-o; if (p<1) p=1; if (q<1) q=1; e = p*a + q*c; f = p*b + q*d; print e," ",f,"\n"; break; } if (less(x,y,e,f)) { c=e; d=f; } else { a=e; b=f; } }