public static void Main() {
Console.WriteLine(new BigRational(64e-5));
Console.WriteLine(new BigRational(64e-5).ToStringDecimal());
Console.WriteLine((int)new BigInteger((long)int.MaxValue + 5));
Console.WriteLine(new BigRational(15, 15464).ToStringDecimal());
Console.WriteLine(new BigRational(1546464565, 165465).ToStringDecimal());
public readonly partial struct BigRational : IEquatable<BigRational>, IComparable<BigRational>
public static readonly BigRational One = new BigRational(BigInteger.One, BigInteger.One);
public static readonly BigRational Zero = new BigRational(BigInteger.Zero, BigInteger.One);
public readonly BigInteger Numerator;
public readonly BigInteger Denominator;
public BigRational Reduced {
BigInteger gcd = BigInteger.GreatestCommonDivisor(Numerator, Denominator);
BigInteger numerator = Numerator / gcd;
BigInteger denominator = Denominator / gcd;
denominator = BigInteger.Abs(denominator);
return new BigRational(numerator, denominator);
public BigInteger Quotient => Numerator / Denominator;
public BigInteger Remainder => Numerator % Denominator;
public BigRational(BigInteger numerator, BigInteger denominator)
if (denominator == 0) throw new ArgumentOutOfRangeException(nameof(denominator), denominator, "Can't be 0.");
Denominator = denominator;
public BigRational(BigInteger numerator) : this(numerator, BigInteger.One) { }
public int CompareTo(BigRational other)
BigInteger integer = BigInteger.DivRem(Numerator, Denominator, out BigInteger remainder);
BigInteger otherInteger = BigInteger.DivRem(other.Numerator, other.Denominator, out BigInteger otherRemainder);
int comparison = integer.CompareTo(otherInteger);
comparison = remainder.CompareTo(otherRemainder);
public override bool Equals(object obj) => obj is BigRational rational && Equals(rational);
public bool Equals(BigRational other)
BigRational reduced = Reduced;
return reduced.Numerator == other.Numerator && Numerator == other.Numerator;
public override int GetHashCode() => HashCode.Combine(Numerator, Denominator);
public override string ToString()
BigRational reduced = Reduced;
if (reduced.Denominator == 1)
return reduced.Numerator.ToString();
return $"{reduced.Numerator}/{reduced.Denominator}";
public string ToStringMixedFraction()
BigRational reduced = Reduced;
BigInteger quotient = reduced.Quotient;
BigInteger remainder = reduced.Remainder;
return quotient.ToString();
return $"{quotient} {reduced.Remainder}/{reduced.Denominator}";
public string ToStringDecimal()
BigRational reduced = Reduced;
BigInteger quotient = reduced.Quotient;
return $"0.{(((decimal)reduced.Numerator) / ((decimal)reduced.Denominator)).ToString().Substring(2)}";
BigInteger remainder = reduced.Remainder;
return quotient.ToString();
return $"{quotient}.{(((decimal)reduced.Remainder) / ((decimal)reduced.Denominator)).ToString().Substring(2)}";
private static readonly BigInteger ten = new BigInteger(10);
public BigRational(double value)
Numerator = BigInteger.Zero;
Denominator = BigInteger.One;
int sign = Math.Sign(value);
BigInteger numerator = new BigInteger(value);
BigInteger denominator = BigInteger.One;
value = (value - Math.Floor(value)) * 10;
numerator += new BigInteger(value);
BigInteger gcd = BigInteger.GreatestCommonDivisor(numerator, denominator);
Numerator = numerator / gcd;
Denominator = denominator / gcd;