为什么 Python 和 C# 中的按位左移具有不同的值?
Python:
>>> 2466250752<<1
4932501504L
C#:
System.Console.Write((2466250752 << 1).ToString()); // output is 637534208
为什么 Python 和 C# 中的按位左移具有不同的值?
Python:
>>> 2466250752<<1
4932501504L
C#:
System.Console.Write((2466250752 << 1).ToString()); // output is 637534208
您在 C# 中溢出了 32 位(无符号)整数。
在python中,所有整数都是任意大小的。这意味着整数将扩展到所需的任何大小。请注意,我添加了下划线:
>>> a = 2466250752
>>>
>>> hex(a)
'0x9300_0000L'
>>>
>>> hex(a << 1)
'0x1_2600_0000L'
^-------------- Note the additional place
在 C# 中,uint
只有 32 位。当您向左移动时,您超出了整数的大小,导致溢出。
换挡前:
换档后:
注意a
没有1
python显示的领先。
要解决这种情况下的限制,您可以使用ulong
64 位而不是 32 位的 a。这适用于高达 2 64 -1 的值。
Python 确保您的整数不会溢出,而 C# 允许溢出(但在检查的上下文中在溢出时抛出异常)。实际上,这意味着您可以将 Python 整数视为具有无限宽度,而 C#int
或uint
始终为 4 个字节。
请注意,在您的 Python 示例中,值“4932501504L”有一个尾随 L,表示长整数。long
当 int 值发生溢出时,Python 会自动以 long(可用内存宽度的大小,与 C# 的 8 个字节不同)整数执行数学运算。你可以在PEP 237中看到这个想法背后的基本原理。
编辑:要在 C# 中获得 Python 结果,您不能使用普通的int
或long
- 这些类型的大小有限。一种大小仅受内存限制的类型是BigInteger。它会比算术慢int
,long
所以我不建议在每个应用程序上都使用它,但它可以派上用场。
例如,您可以编写与 C# 中几乎相同的代码,并获得与 Python 中相同的结果:
Console.WriteLine(new BigInteger(2466250752) << 1);
// output is 4932501504
这适用于任意班次大小。例如,你可以写
Console.WriteLine(new BigInteger(2466250752) << 1000);
// output is 26426089082476043843620786304598663584184261590451906619194221930186703343408641580508146166393907795104656740341094823575842096015719243506448572304002696283531880333455226335616426281383175835559603193956495848019208150304342043576665227249501603863012525070634185841272245152956518296810797380454760948170752
当然,这会溢出很长时间。