Let's try this:
First, we need to turn the float into a fraction. The easiest way I can do this is to find the order of magnitude of epsilon, multiply the float by that order and truncate to get the numerator.
long orderOfMagnitude = 1 while(epsilon * orderOfMagnitude <1) orderOfMagnitude *= 10; numerator = (int)(target_real*orderOfMagnitude); denominator = orderOfMagnitude;
Now we can split the fraction into the smallest terms. The most effective way that I know is to try dividing by all primes less than or equal to the square root of a smaller number of numerator and denominator.
var primes = new List<int>{2,3,5,7,11,13,17,19,23}; //to start us off var i = 0; while (true) { if(Math.Sqrt(numerator) < primes[i] || Math.Sqrt(denominator) < primes[i]) break; if(numerator % primes[i] == 0 && denominator % primes[i] == 0) { numerator /= primes[i]; denominator /= primes[i]; i=0; } else { i++; if(i > primes.Count) { //Find the next prime number by looking for the first number not divisible //by any prime < sqrt(number). //We are actually unlikely to have to use this, because the denominator //is a power of 10, so its prime factorization will be 2^x*5^x var next = primes.Last() + 2; bool add; do { add = true; for(var x=0; primes[x] <= Math.Sqrt(next); x++) if(next % primes[x] == 0) { add = false; break; } if(add) primes.Add(next); else next+=2; } while(!add); } } }
source share