我们知道-2*4 ^ 31 + 1 = -9.223.372.036.854.775.807,你可以在long long中存储的最低值,如下所述:整数类型在C++中存储的值的范围.所以我有这个操作:
#include <iostream>
unsigned long long pow(unsigned a, unsigned b) {
unsigned long long p = 1;
for (unsigned i = 0; i < b; i++)
p *= a;
return p;
}
int main()
{
long long nr = -pow(4, 31) + 5 -pow(4,31);
std::cout << nr << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
为什么它显示-9.223.372.036.854.775.808而不是-9.223.372.036.854.775.803?我正在使用Visual Studio 2015.
Mar*_*ica 15
这是一个非常讨厌的小问题,有三个(!)原因.
首先,存在浮点运算是近似的问题.如果编译器选择一个pow返回float或double 的函数,那么4**31是如此之大,以至于5小于1ULP(精度最低的单位),所以添加它将无效(换句话说,4.0**31 + 5 = = 4.0**31).乘以-2可以毫无损失地完成,并且结果可以long long作为错误的答案存储在一起而不会丢失:-9.223.372.036.854.775.808.
其次,标准头可以包括其他标准头,但不是必需的.显然,Visual Studio的<iostream>包含版本<math.h>(pow在全局命名空间中声明),但Code :: Blocks版本没有.
第三,OP的pow函数没有被选中,因为他传递参数4,并且31它们都是类型int,并且声明的函数具有类型的参数unsigned.从C++ 11开始,有很多重载(或函数模板)std::pow.这些都返回float或double(除非其中一个参数属于类型long double- 这里不适用).
因此,重载std::pow将是更好的匹配...具有双返回值,并且我们得到浮点舍入.
故事的道德:除非你真的知道自己在做什么,否则不要编写与标准库函数同名的函数!
| 归档时间: |
|
| 查看次数: |
2056 次 |
| 最近记录: |