36 const int sign = ( value > 0 ) ? 1 : -1;
37 const double x = std::abs( value );
41 long long previousAConvergent = 0;
42 long long currentAConvergent = 1;
44 long long previousBConvergent = 1;
45 long long currentBConvergent = 0;
47 double fractionalPart = x;
48 const double relativeTolerance = tolerance * x;
50 for (
int i = 0; i < maxIterations; ++i )
52 long long a =
static_cast< long long >( std::floor( fractionalPart ) );
55 if ( currentAConvergent != 0 && a > ( std::numeric_limits<long long>::max() - previousAConvergent ) / currentAConvergent )
59 if ( currentBConvergent != 0 && a > ( std::numeric_limits<long long>::max() - previousBConvergent ) / currentBConvergent )
64 long long nextHConvergent = a * currentAConvergent + previousAConvergent;
65 long long nextKConvergent = a * currentBConvergent + previousBConvergent;
66 previousAConvergent = currentAConvergent;
67 previousBConvergent = currentBConvergent;
68 currentAConvergent = nextHConvergent;
69 currentBConvergent = nextKConvergent;
72 if ( currentBConvergent != 0 && std::abs( x -
static_cast<double>( currentAConvergent ) /
static_cast<double>( currentBConvergent ) ) <= relativeTolerance )
79 const double remainder = fractionalPart -
static_cast< double >( a );
85 fractionalPart = 1.0 / remainder;
88 numerator = sign * currentAConvergent;
89 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.
static double roundingInterval(double span, int divisions=10)
Returns a round interval, a power of ten, which splits the given span into at least divisions parts.
double qgsRound(double number, int places)
Returns a double number, rounded (as close as possible) to the specified number of places.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).