You can solve this problem using Continued Fractions.
As stated in comments, you can't obtain a fraction (a rational number) that exactly represents an irrational number, but you can get pretty close.
I implemented once, in a pet project, a rational number type. You can find it here. Look into TryFromDouble
for an example of how to get the closest rational number (with specified precision) to any given number using Continued Fractions.
An extract of relevant code is the following (I will
Not post the whole type implementation because it is too long, but the code should still be pretty understandable):
public static bool TryFromDouble(double target, double precision, out Rational result)
{
//Continued fraction algorithm: http://en.wikipedia.org/wiki/Continued_fraction
//Implemented recursively. Problem is figuring out when precision is met without unwinding each solution. Haven't figured out how to do that.
//Current implementation computes rational number approximations for increasing algorithm depths until precision criteria is met, maximum depth is reached (fromDoubleMaxIterations)
//or an OverflowException is thrown. Efficiency is probably improvable but this method will not be used in any performance critical code. No use in optimizing it unless there is
//a good reason. Current implementation works reasonably well.
result = zero;
int steps = 0;
while (Math.Abs(target - Rational.ToDouble(result)) > precision)
{
if (steps > fromDoubleMaxIterations)
{
result = zero;
return false;
}
result = getNearestRationalNumber(target, 0, steps++);
}
return true;
}
private static Rational getNearestRationalNumber(double number, int currentStep, int maximumSteps)
{
var integerPart = (BigInteger)number;
double fractionalPart = number - Math.Truncate(number);
while (currentStep < maximumSteps && fractionalPart != 0)
{
return integerPart + new Rational(1, getNearestRationalNumber(1 / fractionalPart, ++currentStep, maximumSteps));
}
return new Rational(integerPart);
}