为什么地板(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++?
我需要找到给定数字(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
相关文章:
- 代码在main()中运行,但在函数中出现错误
- 链接阶段在Ubuntu上失败,但在MacOS上失败
- 对C宏的未定义引用,但在定义它时会出现重新定义错误
- c++17文件系统::recursive_directory迭代器()在mac上没有给出这样的目录,但在windows上
- 断言中的Fold表达式在某些计算机上编译,但在其他计算机上不编译
- 换位表导致测试失败(但在游戏中运行良好)
- 库标题在标题中不可见,但在 cmake build 下.cpp文件中完全可见.为什么?
- 打印矩阵后分割错误,但在打印额外行后修复(ostream <<操作器)
- 为什么数组在一个文件中打印,但在发送到另一个文件时却缺少数字
- C++代码在 Gedit 中有效,但在 VS 中不起作用(它只是打印"按任意键退出......"。消息)
- 试图打印数组,但在打印之前正在输入一条新线路
- 为什么地板(POW(64,1.0/3))返回3但在C 中卸下地板()时打印4
- 在C 内部打印,但在情况之外打印
- C++中是否已经有一些类可以打印到 cout,但在未定义某些宏时可以关闭(例如 DEBUG)
- Gtest:捕获输出,但在失败时打印
- 读取文件,但打印不在读取文件中的整数
- 打印浮点精度为 2,但在C++中没有小数 (.)
- 结构数组在被调用时打印零,但在未被调用时显示正确的输入(短代码)
- 在读取文件时打印出正确的值,但在读取文件后打印出垃圾值
- 在我的C++代码中,如果我在循环外打印sum,它会给出正确的答案,但在任何循环中都不会,为什么不呢