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)https://en.wikipedia.org/wiki/Continued_fraction
algorithm.
Fraction.fromDouble(3.8) // represented as 19/5
Note that irrational numbers can not be represented as fractions, so if you try to use this method on π (3.1415...) you won't get a valid result.
Fraction.fromDouble(math.pi)
The above returns a fraction because the algorithm considers only 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 pi because irrational numbers cannot be expressed as fractions.
This method is good with rational numbers.
Implementation
factory Fraction.fromDouble(double value, {double precision = 1.0e-12}) {
_checkValue(value);
_checkValue(precision);
// Storing the sign
final mul = (value >= 0) ? 1 : -1;
final x = value.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 = value.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.toInt(), k1.toInt());
}