34 const int sign = ( value > 0 ) ? 1 : -1;
35 const double x = std::abs( value );
39 long long previousAConvergent = 0;
40 long long currentAConvergent = 1;
42 long long previousBConvergent = 1;
43 long long currentBConvergent = 0;
45 double fractionalPart = x;
46 const double relativeTolerance = tolerance * x;
48 for (
int i = 0; i < maxIterations; ++i )
50 long long a =
static_cast< long long >( std::floor( fractionalPart ) );
53 if ( currentAConvergent != 0 && a > ( std::numeric_limits<long long>::max() - previousAConvergent ) / currentAConvergent )
57 if ( currentBConvergent != 0 && a > ( std::numeric_limits<long long>::max() - previousBConvergent ) / currentBConvergent )
62 long long nextHConvergent = a * currentAConvergent + previousAConvergent;
63 long long nextKConvergent = a * currentBConvergent + previousBConvergent;
64 previousAConvergent = currentAConvergent;
65 previousBConvergent = currentBConvergent;
66 currentAConvergent = nextHConvergent ;
67 currentBConvergent = nextKConvergent;
70 if ( currentBConvergent != 0 && std::abs( x -
static_cast<double>( currentAConvergent ) /
static_cast<double>( currentBConvergent ) ) <= relativeTolerance )
77 const double remainder = fractionalPart -
static_cast< double >( a );
83 fractionalPart = 1.0 / remainder;
86 numerator = sign * currentAConvergent;
87 denominator = currentBConvergent;
static Q_INVOKABLE void doubleToRational(double value, qlonglong &numerator, qlonglong &denominator, double tolerance=1.0e-9, int maxIterations=100)
Converts a double value to a rational fraction.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).