一道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。
如果我运行下面的程序:
#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。