Home > OS >  Exact double division
Exact double division

Time:12-02

Consider the following function:

auto f(double a, double b) -> int
{
  return std::floor(a/b);
}

So I want to compute the largest integer k such that k * b <= a in a mathematical sense. As there could be rounding errors, I am unsure whether the above function really computes this k. I do not worry about the case that k could be out of range. What is the proper way to determine this k for sure?

CodePudding user response:

It depends how strict you are. Take a double b and an integer n, and calculate bn. Then a will be rounded. If a is rounded down, then it is less than the mathematical value of nb, and a/b is mathematically less than n. You will get a result if n instead of n-1.

On the other hand, a == b*n will be true. So the “correct” result could be surprising.

Your condition was that “kb <= a”. If we interpret this as “the result of multiplying kb using double precision is <= a”, then you’re fine. If we interpret it as “the mathematically exact product of k and b is <= a”, then you need to calculate k*b - a using the fma function and check the result. This will tell you the truth, but might return a result of 4 if a was calculated as 5.0 * b and was rounded down.

CodePudding user response:

The problem is that float division is not exact.

a/b can give 1.9999 instead of 2, and std::floor can then give 1.

One simple solution is to add a small value prior calling std::floor:

std::floor (a/b   1.0e-10);

Result:

result = 10 while 11 was expected
With eps added, result = 11

Test code:


#include <iostream>
#include <cmath>

int main () {
    double b = atan (1.0);
    int x = 11;
    double a = x * b;
    int y = std::floor (a/b);
    std::cout << "result = " << y << " while " << x << " was expected\n";
    
    double eps = 1.0e-10;
    int z = std::floor (a/b   eps);
    std::cout << "With eps added, result = " << z << "\n";
    
    return 0;
}
  • Related