这是昨天我的问题的后续行动:
CMS慷慨地提供了使用按位运算符在C中添加两个数字的示例:
#includeint 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处理这个的方式有区别?
正如我昨天在回答CMS回答中指出的那样,左移一个负数是C中的未定义行为,所以这甚至不能保证在C中工作(问题是如何处理有符号位,你转移它像一个有价值的位置,还是不受转变的影响?标准委员会无法就行为达成一致,因此未定义.
当这种情况恰好在C中工作时,它依赖于固定的位宽整数,以便在进行移位时最左边的位被推离端(它还需要将符号位视为值位以进行移位).C中的所有整数类型都是固定位,但Python数字可以任意大.在Python中左移一个数字只会导致它变大:
>>> 1 << 100 1267650600228229401496703205376L
你可以尝试这样的事情:
x = (a << 1) & 0xffffffff
要将结果限制为32位,问题在于Python中的左移位运算符不会移位有符号数的符号位(这是使特定解决方案工作所需的一部分).可能有一种方法可以改变移位运算符的行为,但我不知道如何.