Rational.fromDouble constructor

Rational.fromDouble(
  1. double number, {
  2. int tolerance = 100,
})

Creates a new Rational from number and tolerance.

Implementation

factory Rational.fromDouble(double number, {int tolerance = 100}) {
  assert(!tolerance.isNegative, 'Tolerance must be positive.');

  if (number == 0) return Rational.zero;

  final sign = number.nonZeroSign;
  final absNumber = number.abs();

  final wholePart = absNumber.floor();
  final fractionalPart = absNumber - wholePart;

  var bestNumerator = 1;
  var bestDenominator = 1;
  var minError = (fractionalPart - (bestNumerator / bestDenominator)).abs();

  for (var denominator = 1; denominator <= tolerance; denominator++) {
    final numerator = (fractionalPart * denominator).round();
    final approximation = numerator / denominator;
    final error = (fractionalPart - approximation).abs();

    if (error < minError) {
      bestNumerator = numerator;
      bestDenominator = denominator;
      minError = error;
    }
  }

  final numerator = sign * (wholePart * bestDenominator + bestNumerator);

  return Rational(numerator, bestDenominator);
}