繁体   English   中英

奇怪的unsigned long long int行为

[英]Strange unsigned long long int behavior

我正在使用unsigned long long int进行一些计算,但是

std::cout << std::setprecision(30) << 900000000000001i64+4*pow(10, 16);

输出: 40900000000000000

和这个

std::cout << std::setprecision(30) << 900000000000011i64+4*pow(10, 16);

输出: 40900000000000008

现在,我不知道发生了什么事我试图消除i64尝试打印4*pow(10, 16)给出正确的结果40000000000000000也试图打印40900000000000011直接,它打印正确的结果。 对于10 ^ 14的幂,它可以正常工作,但是此后它开始表现异常。

有人可以解释发生了什么吗?

您得到此尴尬结果的原因是因为丢失了double类型的最低有效位的值。 double尾数只能容纳大约15个十进制数字和正好52个二进制数字( Wiki )。

900000000000001i64+4*pow(10, 16)将转换为对所有低位进行双重修整。 在您的情况下,其中有3个。

例:

std::cout << std::setprecision(30);
std::cout << 900000000000001i64 + 4 * pow(10, 16) << endl;
std::cout << 900000000000002i64 + 4 * pow(10, 16) << endl;
std::cout << 900000000000003i64 + 4 * pow(10, 16) << endl;
std::cout << 900000000000004i64 + 4 * pow(10, 16) << endl;
std::cout << 900000000000005i64 + 4 * pow(10, 16) << endl;
std::cout << 900000000000006i64 + 4 * pow(10, 16) << endl;
std::cout << 900000000000007i64 + 4 * pow(10, 16) << endl;
std::cout << 900000000000008i64 + 4 * pow(10, 16) << endl;
std::cout << 900000000000009i64 + 4 * pow(10, 16) << endl;

将产生结果:

40900000000000000
40900000000000000
40900000000000000
40900000000000000
40900000000000008
40900000000000008
40900000000000008
40900000000000008
40900000000000008
40090000000000008

注意如何将值四舍五入为2 3

请尝试以下代码(请注意此处的显式类型转换)。

typedef unsigned long long ULONG64; //Not a must, but just for code clarity

std::cout << std::setprecision(30) << 900000000000001i64 + (ULONG64)(4 * pow(10, 16));
//output -> 40900000000000001
std::cout << std::setprecision(30) << 900000000000011i64 + (ULONG64)(4 * pow(10, 16));
//output -> 40900000000000011

您必须告诉编译器对pow(...)函数返回的结果进行显式类型转换(转换为ULONG64),类型为double。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM