一道C++大整数乘法时的精度问题

A C++ large integer precision question during multiplication

如果我运行下面的程序:

#include <iostream>

int main()
{
   using namespace std;

   uint64_t f12 = 18446744073709551568;
   uint64_t f3 = 2;
   uint64_t f123 = f12 * f3;

   cout << f12 << endl;
   cout << f3 << endl;
   cout << f123 << endl;

   return 0;

}

我得到输出:

18446744073709551568
2
18446744073709551520

我不明白为什么 2 次 f12 得到的值要小(刚好是 48)。如果因为达到uint64值的大小而翻滚,那岂不是大不相同(除非这是一个极端的巧合)?

你可以把它归结为“极度巧合”。 18446744073709551568 二进制是

FFFFFFFFFFFFFFD0

我们学二进制的时候都发现,乘以2相当于左移,变成:

FFFFFFFFFFFFFFA0

注意D0

11010000

在二进制中,设置了高位,因此左移低 8 位变为

10100000

A0(高位向左进位)。

现在,通过计算 FFFFFFFFFFFFFFA0 的十进制数,您将得到问题的答案(您已经获得了一些线索,因为 A0 小于 D0 30 十六进制,这恰好是 48,纯属偶然)。

整数值乘以2可以看作是位的左移。当您将数字 18446744073709551568 转换为二进制时,那么这是...

1111111111111111111111111111111111111111111111111111111111010000

如果将这些位左移一位,则结果是...

1111111111111111111111111111111111111111111111111111111110100000

在最低有效字节,即右端,11010000(十进制208)被10100000(十进制160)代替,正好你的 48 少了。所有高位有效字节保持不变。所以总体结果也少 48

转移是转移注意力。

C++ 中的 64 位无符号数学是数学模 2 的 64 次方。如果 2*a 比 a 小 48,则 a 是 2 的 64 次方减去 48。