3

私はビット演算でF#ドキュメントを見ていました:

ビット単位の右シフト演算子。結果は、ビットが2番目のオペランドのビット数だけ右にシフトされた最初のオペランドです。最下位位置からシフトされたビットは、最上位位置に回転されません。符号なしタイプの場合、最上位ビットにはゼロが埋め込まれます。符号付きタイプの場合、最上位ビットには1が埋め込まれます。2番目の引数の型はint32です。

MSBがゼロで埋められているC++言語(そしておそらくCも)と比較して、この設計選択の背後にある動機は何でしたか?例えば:

int mask = -2147483648 >> 1; // C++ code

ここで-2147483648=

10000000 00000000 00000000 00000000

マスクは1073741824に等しい

ここで1073741824=

01000000 00000000 00000000 00000000

これで、同じコードをF#(またはC#)で作成すると、実際にMSBにコードが埋め込まれ、-1073741824になります。

ここで-1073741824=

11000000 00000000 00000000 00000000
4

2 に答える 2

6

符号付きシフトには、xを右にnシフトすることがfloor(x / 2 n)に対応するという優れた特性があります。

.NETには、両方のタイプの操作(符号付きシフトを実行するため、および符号なしシフトを実行するため)用のCILオペコードがありshrますshr.un。F#とC#は、シフトされるタイプの符号に基づいて、使用するオペコードを選択します。つまり、他の動作が必要な場合は、シフトの前後に数値変換を実行するだけで済みます(CLRに数値が格納される方法により、実際には実行時の影響はありません。スタック上のint32はuint32と区別できません)。 。

于 2010-09-29T22:12:59.817 に答える
5

改革された質問に答えるには(コメントで):

CおよびC++標準では、負の値を右シフトした結果は定義されていません(実装定義か未定義のどちらかで、どちらかは思い出せません)。

これは、標準が、基礎となる命令セットの観点から最小公分母を反映するように定義されているためです。たとえば、真の算術シフトを実行するには、命令セットにasrプリミティブが含まれていない場合、いくつかの命令が必要です。これは、標準が1または2の補数表現を義務付けているという事実によってさらに複雑になります。

于 2010-09-29T22:02:52.933 に答える