cmath精度误差中的楼层函数

Floor functions in cmath precision error

本文关键字:函数 精度 误差 cmath      更新时间:2023-10-16

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

#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 %llun",ull(ans1),ull(ans2));
}

输出

20833333333333333 20833333333333332

这个问题中,我不得不在决赛中四舍五入。我首先使用了 cmath 的圆形函数,但得到了 WA。然后经过一些谷歌搜索,我发现了这种很好的简单方法来四舍五入一个 no

n = floor(n + 0.5);

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

我的猜测是,来自 std 命名空间的地板函数返回一个长双精度值,而来自 cmath 的普通地板函数返回一个双精度值,因此精度损失。

所以我想知道的是为什么这两个函数在 cmath 中位于不同的命名空间中,如果编译器选择合适的地板函数不是更好吗,因为我正在传递给它一个"长双精度",就像普通方法重载一样。

谢谢

cmath 的 floor 函数是 C 的遗产,在C++提出 floorlong double 版本之前就在这里......现在我们无法删除它,因为它被使用,所以新的是在 std 中创建的。

floor(ans+0.5)会将(ans + 0.5)转换为"正常"双精度,因此会失去精度。