Fraction.fromDouble constructor
Tries to give a fractional representation of a double according with the given precision. This implementation takes inspiration from the continued fraction algorithm.
Fraction.fromDouble(3.8) // represented as 19/5
Note that irrational numbers can not be represented as fractions. If you try to use this method on π (3.1415...) for example, you won't get a valid result:
Fraction.fromDouble(math.pi)
The above code doesn't throw. It returns a Fraction object because the
algorithm only considers the first 10 decimal digits (since precision
is set to 1.0e-10).
Fraction.fromDouble(math.pi, precision: 1.0e-20)
This example will return another different value because it considers the first 20 digits. It's still not a fractional representation of π because irrational numbers cannot be expressed as fractions.
You should only use this method with rational numbers.
Implementation
factory Fraction.fromDouble(double value, {double precision = 1.0e-12}) {
_checkValue(value);
_checkValue(precision);
// Storing the sign
final abs = value.abs();
final mul = (value >= 0) ? 1 : -1;
final x = abs;
// How many digits is the algorithm going to consider
final limit = precision;
var h1 = 1;
var h2 = 0;
var k1 = 0;
var k2 = 1;
var y = abs;
do {
final a = y.floor();
var aux = h1;
h1 = a * h1 + h2;
h2 = aux;
aux = k1;
k1 = a * k1 + k2;
k2 = aux;
y = 1 / (y - a);
} while ((x - h1 / k1).abs() > x * limit);
// Assigning the computed values
return Fraction(mul * h1, k1);
}