在cmath精度错误中的floor函数

时间:2014-03-02 18:15:10

标签: c++ algorithm floating-point floating-point-precision

所以我最近尝试了一个涉及浮点运算的问题。下面是该代码的片段。

#include<cstdio>
#include<cmath>
typedef unsigned long long ull;

int main(){
    long double n=1000000000,ans,ans1,ans2;
    ans = (n*n/48.0);

    ans1 = std::floor(ans+0.5); // Correct, got AC with this
    ans2 = floor(ans+0.5);      // Incorrect, got me 2 WA :(

    printf("%llu %llu\n",ull(ans1),ull(ans2));
}

输出

20833333333333333 20833333333333332

在问题中我不得不围绕最后的问题。我首先使用来自cmath的圆形函数,但得到了WA。然后经过一些谷歌搜索,我找到了这个简单的方法来绕过一个没有

n = floor(n + 0.5);

但令我惊讶的是地板功能的奇怪行为。当与std命名空间一起使用时,它的行为会有所不同,实际上它只在那时表现正常。

我的猜测是std命名空间的floor函数返回long double,而cmath的normal floor函数返回double,因此精度损失。

所以我想知道为什么这两个函数在cmath中位于不同的命名空间中,如果编译器选择了适当的floor函数就不会更好,因为我传递了一个'long double',就像普通的方法重载一样。

由于

1 个答案:

答案 0 :(得分:2)

来自cmath的floor函数是来自C的遗产,它就在C ++提出long double floor版{...}}之前......现在我们无法删除它,因为它已被使用,所以新的是在std。

中创建的 floor(ans+0.5)会将(ans + 0.5)转换为'普通'双精度,因此精度会降低。