python - 在 python 中,在二进制运算中对整数取反的好方法是什么?

标签 python python-3.x bit-manipulation twos-complement

根据我读到的内容 the binary representation of integers ,第一位表示符号(正或负)。

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

现在我正在尝试将第一位翻转为 1通过使用x|=(1<<27)但它返回 134217733 .

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

我所做的事情有什么问题吗?

最佳答案

您无法通过仅翻转其表示形式中的一点来将 Python int 从正数切换为负数。您假设它存储在固定长度的二进制补码表示形式中。但Python 3 中的整数不是固定长度的位字符串,并且它们不以二进制补码表示形式存储。相反,它们存储为 30 位或 15 位“数字”的可变长度字符串,符号单独存储(如 signed-magnitude representation )。因此,对 Python int 求反的“最低级别”方法不是使用位运算,而是使用一元 - 运算符,该运算符将切换其符号。 (有关 Python 3 源代码的详细信息,请参阅本答案的末尾。)

(我还应该提到 sys.getsizeof() 不会告诉您 int 中的位数。它为您提供整数所占用的内存字节数对象正在使用。这也不是实际存储的字节数;大部分字节用于其他用途。)


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

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

现在我们可以做一些像您试图做的事情:

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

这表明,在 6 位二进制补码表示中打开数字 2 的高位会将数字变成 -30。这是有道理的,因为 26-1 = 32,因此该表示形式中的最小整数是 -32。 -32 + 2 = -30。


如果您对 Python 3 如何存储整数的详细信息感兴趣,可以查看 Objects/longobject.c在源中。特别是查看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()只是对整数对象的 ob_size 字段的引用。当该值为0时,整数为0。否则,其符号为整数的符号,其绝对值为保存该整数绝对值的数组中30位或15位数字的个数。

关于python - 在 python 中,在二进制运算中对整数取反的好方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37135106/

相关文章:

python - 如何将 Bokeh 中的 slider 值传递回 Python 代码

python - 使用 Pillow 将 png 转换为 jpeg

c++ - 我如何测试所有位是否已设置或所有位都未设置?

python - 如何将整数转换为可变长度字节字符串?

python - 在 python 中使用 scipy 的 kmeans2 函数

python - 使用 numpy 通过另一个列表对矩阵的行和列进行排序

python - Python中的时间问题

python - 列表理解 - 连接每个子列表中的第 n 个项目

c - 如何将两个 uint32_t 值交错为一个 uint64_t?

从 iframe 中动态加载的表中抓取时出现 Python Selenium 超时异常