Python 中的按位减法
这是 我昨天的问题:
CMS 善意地提供了这个在 C 中使用按位运算符将两个数字相加的示例:
#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 处理这个问题的方式会有区别吗?
This is a follow-up to my question yesterday:
CMS kindly provided this example of using bitwise operators to add two numbers in C:
#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;
}
It works great and I then ported it to Python as follows:
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)
They both work for addition and the C program works for subtraction as well. However, the Python program enters an infinite loop for subtraction. I am trying to get to the bottom of this and have posted the program here for further experimentation: http://codepad.org/pb8IuLnY
Can anyone advise why there would be a difference between the way C handles this and the way CPython handles this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
正如我昨天在对 CMS 的回答的回复中指出的,左移负数在 C 中是未定义的行为,所以这甚至不能保证在 C 中工作(问题是如何处理有符号位,你会移动它吗?就像一个值位或者它不受转变的影响吗?标准委员会无法就行为达成一致,因此它未定义)。
当这种情况在 C 中发生时,它依赖于固定位宽整数,因此当您进行移位时,最左边的位会被推到末尾(它还需要将符号位视为用于移位目的的值位)。 C 中的所有整数类型都是固定位的,但 Python 数字可以是任意大。 在Python中左移一个数字只会导致它变得越来越大:
你可以尝试这样的事情:
要将结果限制为32位,问题是Python中的左移运算符不会移动a的符号位有符号数(这是使该特定解决方案发挥作用所需的一部分)。 可能有一种方法可以改变轮班操作员的行为,但我不知道如何做。
As I pointed out in my response to CMS' answer yesterday, left-shifting a negative number is undefined behavior in C so this isn't even guaranteed to work in C (the problem is how to handle the signed bit, do you shift it like a value bit or is it not affected by a shift? The standards committee couldn't agree on a behavior so it was left undefined).
When this happens to work in C it relies on fixed bit-width integers so that the leftmost bit gets pushed off the end when you do a shift (it also requires the sign bit to be treated as a value bit for shifting purposes). All integer types in C are fixed-bit but Python numbers can be arbitrarily large. Left-shifting a number in Python just causes it to keep getting larger:
You could try something like this:
To limit the result to 32-bits, the problem is that the left shift operator in Python doesn't shift the sign bit of a signed number (which is part of what is required to make this particular solution work). There might be a way to change the behavior of the shift operator but I don't know how.
负数移位在 python 和 C 之间没有一致的解释。
Shifting negative numbers doesn't have consistent interpretation between python and C.
如果
i
、j
是两个整数:加法:
if
i
,j
are two integers:addition:
我注意到您假设 python 处理数字的方式与 C 相同。
这并不完全正确。 这意味着 C 的 int 数字具有 16 位的固定长度。 有关 C 数据类型的详细信息,您可以参考 en.wikipedia.org 上的 C_data_types
另一方面,据说 Python 的 int 数字实际上具有无限长度。
添加正整数可能会以同样的方式工作。 但负整数的减法或加法不应该是简单的映射转换。
理解这一点的一个简单方法是一个关于负数的小例子:
想象一下 3 位的固定长度整数表示:
#无符号#
000
: 0001
: 1010
: 2011
: 3100
> : 4101
: 5110
: 6111
: 7#Signed:#
000
: 0001
: 1010
: 2011
: 3100
: -4101
: -3111
: -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 中却行不通。
I've noticed that you're assuming that python works with numbers the same way as C does.
Thats not entirely true. Meaning C's int numbers have a fixed length of 16 bits. For detailed info on C datatypes you can refer to C_data_types on en.wikipedia.org
Python, on the other hand, is said to have a virtually infinite length for int numbers.
Adding positive integers may work the same way. But subtracting or adding negative integers shouldn't be a simple mapping translation.
An easy way to understand this is a little example on negative numbers:
Imagine a fixed length integer representation of 3 bits:
#Unsigned#
000
: 0001
: 1010
: 2011
: 3100
: 4101
: 5110
: 6111
: 7#Signed:#
000
: 0001
: 1010
: 2011
: 3100
: -4101
: -3110
: -2111
: -1This works cool because you can see that
1-3=1+(-3)
, -3 is101
that's 5 if unsigned. So1+5=6
, 6 :110
: -2. This means that1-3=-2
.it also becomes buggy when overflowing:
-4 + -1 = 3
not -5 because it's out of range!3 + 1 = -4
not 4 because it's out of range!As you may see this works for fixed length but it doesn't work this way in Python.
对于任何仍然感兴趣的人,要解决 python 中的问题,只需添加一个新的 case 并切换函数内 x 和 y 的顺序,并返回负值,虽然这在函数中添加了“-”,但这提供了一种方法使用按位运算符。 对于仍然希望在以下问题中使用运算符“-”进行争论的人,我可以认为对于 2 - 6 的情况,正确的答案是 -4,其中答案中存在“-”,因此可以添加当x小于y时。 希望这可以帮助。
#使用位运算符将两个整数相减
#参考:https://www.geeksforgeeks.org /不使用算术运算符减去两个数字/
For anyone are still interested, to resolve issue in python, just add a new case and switch the order of x and y inside the function, and return the negative value, though this put "-" in the function, but this presented a way using bit-wise operator. For anyone still wish to argue using operator "-" in the following question, I could argue that for the case of 2 - 6, the right answer is -4 where "-" exists in the answer, so it might be okay to add it when x is smaller than y. Hope this helps.
#A substract to substract two integers using bits operators
#refer to: https://www.geeksforgeeks.org/subtract-two-numbers-without-using-arithmetic-operators/