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ビットのみです。左にシフトすると、整数のサイズを超えてオーバーフローが発生します。
シフトする前に:
シフト後:
Pythonが示しa
た先頭がないことに注意してください。1
この場合のこの制限を回避するulong
には、32ビットではなく64ビットのaを使用できます。これは、264-1までの値で機能します。
Pythonは整数がオーバーフローしないようにしますが、C#はオーバーフローを許可します(ただし、チェックされたコンテキストでオーバーフロー時に例外をスローします)。実際には、これは、Python整数を無限の幅を持つものとして扱うことができることを意味しますが、C#int
またはuint
は常に4バイトです。
Pythonの例では、値「4932501504L」の末尾にLがあり、これは長整数を意味します。long
Pythonは、int値でオーバーフローが発生した場合に、長い(8バイトであるC#とは異なり、使用可能なメモリ幅のサイズ)整数で自動的に計算を実行します。このアイデアの背後にある理論的根拠は、PEP237で確認できます。
編集:Pythonの結果をC#で取得するには、プレーンを使用することはできません。int
または、long
これらのタイプのサイズには制限があります。サイズがメモリによってのみ制限されるタイプの1つは、BigIntegerです。int
算術演算よりも低速になるlong
ため、すべてのアプリケーションで使用することはお勧めしませんが、便利です。
例として、C#とほぼ同じコードを記述して、Pythonと同じ結果を得ることができます。
Console.WriteLine(new BigInteger(2466250752) << 1);
// output is 4932501504
これは、任意のシフトサイズで機能します。たとえば、あなたは書くことができます
Console.WriteLine(new BigInteger(2466250752) << 1000);
// output is 26426089082476043843620786304598663584184261590451906619194221930186703343408641580508146166393907795104656740341094823575842096015719243506448572304002696283531880333455226335616426281383175835559603193956495848019208150304342043576665227249501603863012525070634185841272245152956518296810797380454760948170752
もちろん、これは長くオーバーフローします。