为什么地板(POW(64,1.0/3))返回3但在C 中卸下地板()时打印4

Why does floor(pow(64,1.0/3)) return 3 but print 4 when the floor() is removed in C++?

本文关键字:打印 但在 返回 POW 为什么      更新时间:2023-10-16

我需要找到给定数字(x)的底部nth root。x可以像1e12一样大,而n可以大于50。floor(pow(64,1.0/3))返回3,请帮助我解决这个问题,如果没有,请建议您牢记牢记吗?

编辑:我知道它关于浮点精度,我问在这种情况下应该是什么。
即使以下代码返回True double x = pow(64,1.0/3); return x==(int)x;

您正在处理良好的旧浮点不精确。与迭代的乘法相比,请参阅std :: pow()的数值稳定性是什么?,尤其是帕斯卡·库克(Pascal Cuoq)的答案,以便深入解释为什么尤其是 std::pow的结果会不准确。由于四舍五入错误,您有时会得到少于4的结果,因此std::floor会落下到3。

我上面链接的答案说:

pow的质量实施将为您提供1 ULP的结果,最佳实现将"保证" 0.5 ULP。

ulp在这里指的是最低精度或单位的单位。了解此错误,您可以在调用std::floor之前增加std::pow()结果。做到这一点的好方法是使用std::nextafter,它为您提供下一个可代表的浮点值(即1 ULP)。我认为,如果帕斯卡(Pascal)对std::pow()的精确度的陈述,则在您的特定示例中,呼叫nextafter曾经将您恢复到4上。这是我推荐的代码:

template <typename T>
T floorroot2(T x, T e)
{
  const auto r = std::pow(x, T(1.0)/e);
  return std::floor(std::nextafter(r, r+1));
}

对我有用(实时示例),但是如果您想额外确定如果您不信任库的pow实现,则可能需要添加2 ULP,即致电nextafter(nextafter(r, r+1), r+1)

#include <iostream>
#include <cmath>
using namespace std;
template<class Type>
Type compute(Type v1, Type v2, Type v3)
{
    return std::floor(std::pow(v1, v2 / v3));
}
int main() {
    std::cout << compute<float>(64, 1, 3) << std::endl;
    std::cout << compute<double>(64, 1, 3) << std::endl;
    std::cout << compute<long double>(64, 1, 3) << std::endl;
}

预期输出:

4
3
4
相关文章: