9

これは昨日の私の質問へのフォローアップです:

CMS は親切にも、C でビット単位の演算子を使用して 2 つの数値を加算する次の例を提供してくれました。

#include<stdio.h>

int add(int x, int y) {
    int a, b;
    do {
        a = x & y;
        b = x ^ y;
        x = a << 1;
        y = b;
    } while (a);
    return b;
}

int main( void ){
    printf( "6 + 3 = %d", add(6,3));
    printf( "6 - 3 = %d", add(6,-3));
    return 0;
}

それはうまく機能し、次のようにPythonに移植しました。

def add(x, y):
    while True:
        a = x & y
        b = x ^ y
        x = a << 1
        y = b
        if a == 0:
            break
    return b

print "6 + 3 = %d" % add(6,3)
print "6 - 3 = %d" % add(6,-3)

どちらも足し算に使用でき、C プログラムは引き算にも使用できます。ただし、Python プログラムは減算のために無限ループに入ります。私はこれを理解しようとしており、さらに実験するためにここにプログラムを投稿しました: http://codepad.org/pb8IuLnY

Cがこれを処理する方法とCPythonがこれを処理する方法に違いがある理由を誰かアドバイスできますか?

4

4 に答える 4

9

昨日のCMSの回答に対する私の回答で指摘したように、負の数を左シフトすることはCでは未定義の動作であるため、これがCで機能することは保証されていません(問題は、符号付きビットをどのように処理するかです。シフトしますか?値ビットのようなものですか、それともシフトの影響を受けませんか? 標準化委員会は動作について合意できなかったため、未定義のままにされました)。

これがたまたまCで機能する場合、固定ビット幅の整数に依存しているため、シフトを行うと左端のビットが最後から押し出されます(また、シフトのために符号ビットを値ビットとして扱う必要があります)。C のすべての整数型は固定ビットですが、Python の数値は任意に大きくすることができます。Python で数値を左シフトすると、数値が大きくなり続けるだけです。

>>> 1 << 100
1267650600228229401496703205376L

次のようなことを試すことができます:

x = (a << 1) & 0xffffffff

結果を 32 ビットに制限するために、問題は Python の左シフト演算子が符号付き数値の符号ビットをシフトしないことです (これは、この特定のソリューションを機能させるために必要なものの一部です)。シフト演算子の動作を変更する方法があるかもしれませんが、その方法はわかりません。

于 2008-12-14T17:06:34.233 に答える
2

負の数をシフトすると、Python と C の間で一貫した解釈が行われません。

于 2008-12-14T17:04:34.223 に答える
1

iが 2 つのj整数の場合:

添加:

printf("%d",(i^j)|((i&j)<<1));
于 2010-08-15T13:43:38.657 に答える
0

Python が C と同じように数値を扱うと想定していることに気付きました。
それは完全に真実ではありません。つまり、C の int 数値は 16 ビットの固定長です。C データ型の詳細については、en.wikipedia.org の C_data_types を
参照してください 。 一方、Python では、int 型の数値は事実上無限の長さであると言われています。
正の整数を追加しても同じように機能する場合があります。ただし、負の整数の減算または加算は、単純なマッピング変換であってはなりません。
これを理解する簡単な方法は、負の数の小さな例です: 3 ビットの固定長整数表現を想像してください:
#Unsigned#

  • 000: 0
  • 001: 1
  • 010: 2
  • 011: 3
  • 100:4
  • 101:5
  • 110:6
  • 111: 7

#署名:#

  • 000: 0
  • 001: 1
  • 010: 2
  • 011: 3
  • 100: -4
  • 101: -3
  • 110: -2
  • 111: -1

1-3=1+(-3), -3 は101署名されていない場合は 5 であることがわかるため、これはうまく機能します。つまり1+5=6、6 : 110: -2 です。これは、1-3=-2.
オーバーフローするとバグが発生します。

  • -4 + -1 = 3範囲外なので-5ではありません!
  • 3 + 1 = -4範囲外なので4ではありません!

ご覧のとおり、これは固定長では機能しますが、Python ではこのようには機能しません。

于 2015-06-11T16:46:23.403 に答える