2

考虑以下函数:

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

所以我想在数学意义上k计算最大的整数。k * b <= a由于可能存在舍入错误,我不确定上述函数是否真的计算 this k。我不担心k可能超出范围的情况。确定这一点的正确方法是什么k

4

2 回答 2

1

这取决于你有多严格。取一个 double b 和一个整数 n,并计算 b n。然后 a 将被四舍五入。如果 a 向下舍入,则它小于 n b 的数学值,并且 a/b 在数学上小于 n。如果 n 而不是 n-1,您将得到一个结果。

另一方面,a == b*n 为真。因此,“正确”的结果可能令人惊讶。

你的条件是“k b <= a”。如果我们将其解释为“使用双精度乘以 k b 的结果是 <= a”,那么你很好。如果我们将其解释为“k 和 b 的数学精确乘积 <= a”,那么您需要使用 fma 函数计算 k*b - a 并检查结果。这将告诉您真相,但如果 a 计算为 5.0 * b 并向下舍入,则可能返回 4 的结果。

于 2021-12-02T07:47:02.790 回答
-1

问题是浮点除法不准确。

a/b可以给1.9999而不是2,然后std::floor可以给1

一个简单的解决方案是在调用之前添加一个小值std::floor

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

结果:

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

测试代码:


#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;
}
于 2021-12-02T09:32:35.703 回答