奇怪的无符号long long int行为

Sar*_*ngh 1 c++ unsigned-long-long-int

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

std::cout << std::setprecision(30) << 900000000000001i64+4*pow(10, 16);
Run Code Online (Sandbox Code Playgroud)

给出输出:40900000000000000

还有这个

std::cout << std::setprecision(30) << 900000000000011i64+4*pow(10, 16);
Run Code Online (Sandbox Code Playgroud)

给出输出:40900000000000008

现在我不知道发生了什么我尝试删除i64尝试打印4*pow(10, 16)给出正确的结果40000000000000000也尝试40900000000000011直接打印,它打印正确的结果.它适用于10 ^ 14的功率但在此之后它开始表现得很奇怪.

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

Iva*_*nko 7

你得到这个尴尬结果的原因是因为丢失了double类型中最低有效位的值.double尾数只能容纳15个十进制数字和52个二进制数字(维基).

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;
Run Code Online (Sandbox Code Playgroud)

会产生结果:

40900000000000000
40900000000000000
40900000000000000
40900000000000000
40900000000000008
40900000000000008
40900000000000008
40900000000000008
40900000000000008
40090000000000008
Run Code Online (Sandbox Code Playgroud)

请注意值如何舍入为2 3.