Your intuition about what should be happening is correct, there is indeed a bug in the constructor that takes a double, if you change it to this it should work for you:
// BigRational(Double)
public BigRational(Double value) {
if (Double.IsNaN(value)) {
throw new ArgumentException("Argument is not a number", "value");
}
else if (Double.IsInfinity(value)) {
throw new ArgumentException("Argument is infinity", "value");
}
bool isFinite;
int sign;
int exponent;
ulong significand;
SplitDoubleIntoParts(value, out sign, out exponent, out significand, out isFinite);
if (significand == 0) {
this = BigRational.Zero;
return;
}
m_numerator = significand;
m_denominator = BigInteger.One;
if (exponent > 0) {
m_numerator = m_numerator << exponent;
}
else if (exponent < 0) {
m_denominator = m_denominator << exponent;
}
if (sign < 0) {
m_numerator = BigInteger.Negate(m_numerator);
}
Simplify();
}
