在python中对二进制运算求反的整数的好方法是什么? [英] What is good way to negate an integer in binary operation in python?

查看:117
本文介绍了在python中对二进制运算求反的整数的好方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基于我对整数的二进制表示形式的了解,第一位用于符号(正或负).

Based on what I've read about the binary representation of integers, the first bit is for sign (positive or negative).

假设我们有一个整数x = 5,而sys.getsizeof(x)返回28(即28位的二进制表示形式).

Let's say we have an integer x = 5 and sys.getsizeof(x) returns 28 (that is binary representation in 28 bit).

目前,我正尝试使用x|=(1<<27)将第一位翻转到1,但它会返回134217733.

For now I am trying to flip the first bit to 1 by using x|=(1<<27)but it returns 134217733.

我只是想知道它是否需要为负数? (不是-5)

I was just wondering whether it needs to be some negative number? (not -5)

我的工作有什么问题吗?

Is there anything wrong with what I am doing?

推荐答案

仅通过稍微改变一下Python的表示形式,就无法将Python int从正数切换为负数.您假设它以固定长度的二进制补码表示形式存储.但是Python 3中的整数不是固定长度的位字符串,也不以二进制补码形式存储.而是将它们存储为30或15位数字"的变长字符串,并单独存储符号(例如符号幅度表示).因此,否定Python int的最低级别"方法不是使用位操作,而是使用一元-运算符,该运算符将切换其符号. (有关Python 3来源的详细信息,请参见此答案的结尾.)

You can't switch a Python int from positive to negative the way you're trying to, by just flipping a bit in its representation. You're assuming it's stored in a fixed-length two's complement representation. But integers in Python 3 are not fixed-length bit strings, and they are not stored in a two's complement representation. Instead, they are stored as variable-length strings of 30- or 15-bit "digits", with the sign stored separately (like a signed-magnitude representation). So the "lowest-level" way to negate a Python int is not with bit operations, but with the unary - operator, which will switch its sign. (See the end of this answer for details from the Python 3 source.)

(我还要提到 sys.getsizeof() 确实可以 not 告诉您int中的位数,它为您提供整数对象正在使用的内存字节数,这也不是实际存储的数字的字节数.这些字节中的大多数用于其他用途.)

(I should also mention that sys.getsizeof() does not tell you the number of bits in your int. It gives you the number of bytes of memory that the integer object is using. This is also not the number of bytes of the actual stored number; most of those bytes are for other things.)

您仍然可以在Python中通过使用正数int模拟固定长度的位字符串来处理二进制补码表示形式.首先,选择所需的长度,例如6位. (您可以轻松选择更大的数字,例如28或594.)我们可以定义一些有用的常量和函数:

You can still play around with two's complement representations in Python, by emulating a fixed-length bit string using a positive int. First, choose the length you want, for example 6 bits. (You could just as easily choose larger numbers like 28 or 594.) We can define some helpful constants and functions:

BIT_LEN = 6
NUM_INTS = 1 << BIT_LEN         # 0b1000000
BIT_MASK = NUM_INTS - 1         #  0b111111
HIGH_BIT = 1 << (BIT_LEN - 1)   #  0b100000

def to2c(num):
    """Returns the two's complement representation for a signed integer."""
    return num & BIT_MASK

def from2c(bits):
    """Returns the signed integer for a two's complement representation."""
    bits &= BIT_MASK
    if bits & HIGH_BIT:
        return bits - NUM_INTS

现在我们可以做您尝试做的事情:

Now we can do something like you were trying to:

>>> x = to2c(2)
>>> x |= 1 << 5
>>> bin(x)
'0b100010'
>>> from2c(x)
-30

这表明在6位二进制补码表示法中打开数字2的高位会使数字变为-30.这是有道理的,因为2 6-1 = 32,所以此表示形式中的最低整数是-32.而-32 + 2 = -30.

Which shows that turning on the high bit for the number 2 in a 6-bit two's complement representation turns the number into -30. This makes sense, because 26-1 = 32, so the lowest integer in this representation is -32. And -32 + 2 = -30.

如果您对Python 3如何存储整数的细节感兴趣,可以查看 Objects/longobject.c .特别是,查看函数_PyLong_Negate() :

If you're interested in the details of how Python 3 stores integers, you can look through Objects/longobject.c in the source. In particular, looking at the function _PyLong_Negate():

/* If a freshly-allocated int is already shared, it must
   be a small integer, so negating it must go to PyLong_FromLong */
Py_LOCAL_INLINE(void)
_PyLong_Negate(PyLongObject **x_p)
{
    PyLongObject *x;

    x = (PyLongObject *)*x_p;
    if (Py_REFCNT(x) == 1) {
        Py_SIZE(x) = -Py_SIZE(x);
        return;
    }

    *x_p = (PyLongObject *)PyLong_FromLong(-MEDIUM_VALUE(x));
    Py_DECREF(x);
}

您可以看到,在通常情况下,它所做的全部都是使整数对象的Py_SIZE()值取反. Py_SIZE() 只是对整数对象的字段.当该值为0时,整数为0.否则,其符号为整数的符号,并且其绝对值是保存该整数的绝对值的数组中30位或15位数字的位数.

you can see that all it does in the normal case is negate the Py_SIZE() value of the integer object. Py_SIZE() is simply a reference to the ob_size field of the integer object. When this value is 0, the integer is 0. Otherwise, its sign is the sign of the integer, and its absolute value is the number of 30- or 15-bit digits in the array that holds the integer's absolute value.

这篇关于在python中对二进制运算求反的整数的好方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆