- Tìm số 0 đầu tiên trong một mảng bit
- Unix Hiển thị thông tin về các tập tin khớp với một trong hai mẫu
- Biểu thức chính quy thay thế nhiều tệp
- Ẩn lệnh từ xtrace
>> mask = 0xFFFFFFFF >>> print("{} {:b}".forma-6ren">
>>> x = -4
>>> print("{} {:b}".format(x, x))
-4 -100
>>> mask = 0xFFFFFFFF
>>> print("{} {:b}".format(x & mask, x & mask))
4294967292 11111111111111111111111111111100
>>>
>>> x = 0b11111111111111111111111111111100
>>> print("{} {:b}".format(x, x))
4294967292 11111111111111111111111111111100
>>> print("{} {:b}".format(~(x ^ mask), ~(x ^ mask)))
-4 -100
我无法弄清楚 Python 如何表示负整数,以及位运算的工作原理。据我了解,Python 试图模拟二进制补码,但具有任意数量的位。因此,通常使用 32 位掩码强制 Python 在位操作之前设置整数的标准大小。
正如您在我的示例中看到的,-4 & 0xFFFFFFFF
产生了一个很大的正数。为什么 Python 似乎将其读取为无符号整数,而不是二进制补码负数?稍后,操作 ~(x ^ mask)
应该产生与大正数完全相同的二进制补码位模式,而不是给出 -4
。是什么导致转换为有符号整数?
Cảm ơn!
1 Câu trả lời
TLDR; CPython 整数类型将符号存储在结构的特定字段中。执行按位运算时,CPython 将负数替换为二进制的补码,有时 (!) 执行相反的操作(即用负数替换二进制的补码)。
整数的内部表示是一个 PyLongObject
结构,它包含一个 PyVarObject
结构。 (当 CPython 创建一个新的 PyLong
对象时,它为结构分配内存并为数字分配尾随空间。)这里重要的是 PyLong
的大小:ob_size
嵌入式结构的 PyVarObject
字段包含大小(以数字为单位)整数(数字是 15 位或 30 位数字)。如果整数为负数,则此大小为减去位数。
(引用:https://github.com/python/cpython/blob/master/Include/object.h Và https://github.com/python/cpython/blob/master/Include/longobject.h)
如您所见,内部 CPython 对整数的表示与通常的二进制表示相去甚远。然而,CPython 必须为各种目的提供按位运算。我们来看看the code中的评论:
static PyObject *
long_bitwise(PyLongObject *a,
char op, /* '&', '|', '^' */
PyLongObject *b)
{
/* Bitwise operations for negative numbers operate as though
on a two's complement representation. So convert arguments
from sign-magnitude to two's complement, and convert the
result back to sign-magnitude at the end. */
/* If a is negative, replace it by its two's complement. */
/* Same for b. */
/* Complement result if negative. */
}
为了在位运算中处理负整数,CPython 使用二进制补码(实际上,这是一个二进制补码,但我不详细介绍)。但请注意“符号规则”(名字是我的):结果的符号是应用于数字符号的按位运算符。更准确地说,如果 nega
,结果为负(negx
= 1
为负,0
为正)。 Simplified code:
switch (op) {
case '^': negz = nega ^ negb; break;
case '&': negz = nega & negb; break;
case '|': negz = nega | negb; break;
default: ...
}
另一方面,格式化程序不执行二进制补码,即使是二进制表示:format_long_internal Gọi long_format_binary 并删除两个前导字符,但保留符号。参见 the code:
/* Is a sign character present in the output? If so, remember it
and skip it */
if (PyUnicode_READ_CHAR(tmp, inumeric_chars) == '-') {
sign_char = '-';
++prefix;
++leading_chars_to_skip;
}
long_format_binary
函数不执行任何二进制补码:仅输出以 2 为基数的数字 preceded by the sign.
if (negative) \
*--p = '-'; \
我会按照你的 REPL 序列:
>>> x = -4
>>> print("{} {:b}".format(x, x))
-4 -100
没有什么奇怪的,因为格式中没有二进制补码,而是一个符号。
>>> mask = 0xFFFFFFFF
>>> print("{} {:b}".format(x & mask, x & mask))
4294967292 11111111111111111111111111111100
-4
为负数。因此,它在逻辑与之前被逐位替换为它的二进制补码。您预计结果会变成负数,但请记住“符号规则”:
>>> nega=1; negb=0
>>> nega & negb
0
因此: 1.结果没有负号; 2.结果不补二。你的结果符合“符号规则”,即使这个规则看起来不是很直观。
现在,最后一部分:
>>> x = 0b11111111111111111111111111111100
>>> print("{} {:b}".format(x, x))
4294967292 11111111111111111111111111111100
>>> print("{} {:b}".format(~(x ^ mask), ~(x ^ mask)))
-4 -100
同样, -4
是负数,因此用它的补码 0b11111111111111111111111111111100
代替,然后与 0b11111111111111111111111111111111
异或。结果是 0b11
( 3
)。你取一元补码,又是 0b11111111111111111111111111111100
,但这次符号是负数:
>>> nega=1; negb=0
>>> nega ^ negb
1
因此,如您所料,结果被取反并得到负号。
结论:我想没有完美的解决方案可以让任意长有符号数Và提供按位运算,但文档并没有详细说明所做的选择。
关于负整数的 Python 表示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46993519/
我有一个非常基本的 MySQL 查询,它从数据库表中读取行并将行值添加或减去定义为 $total_balance 的 PHP 字符串。 例如; $statement_details_query = m
我有 following fiddle ,请注意,如果您使输出的宽度变小,图像将被覆盖并且不会出现滚动条 - 完美。 如果我attempt the same effect on the right ,
这个正则表达式将得到 456。我的问题是为什么它不能是 1-234-56 中的 234 ? 56 是否限定 (?!\d)) 模式,因为它不是单个数字。 (?!\d)) 寻找的起始点在哪里? impor
我需要知道两个子结构之间的内存距离 (&my_type.a - &my_tape.b.c) 结果的类型是什么?我需要将它转换为 (signed int),所以显然它是别的东西。 最佳答案 根据 C11
我遇到了一个扩展异常的异常处理程序类,如下所示: public class AppFileReaderException extends Exception { //Explicit seri
如何可视化负 RGB 值? 根据 OpenCV 文档: CV_8S - 8 位有符号整数 (-128..127) 这是否意味着 -128 表示 0 而 127 表示 255? 如果是,那我们为什么需要
我这里有一段代码给我带来了麻烦: idIndex = panoBuffer.indexOf("\"photo_id\":"); System.out.println(idIndex);
我刚刚练习 Java,对此还很陌生。我只是想创建一个随机数生成器程序来跟踪玩家的获胜、失败、获胜百分比和总获胜金额。该程序的逻辑是,玩家每次 session 有 3 次机会,计算机会生成一个随机数,玩
因此,我们被要求创建一个程序,使用户能够从 1-6 个有关矩阵运算的选项中进行选择。在每个用户的输入中,我们需要检查该输入是否适合要完成的操作(程序应该接受整数或 float ,正数或负数)。如果不满
这是我期望的输出 x |x| 1.2 1.2 -2.3 2.3 3.4 3.4 但我一直收到这个: x |x| 1
假设我有这个: $date1=date_create(date('H:I', strtotime('8:00'))); $date2=date_create(date('H:I', strtotime
如何确定负 FixNum 的无符号解释? # unexpected, true (~0b01111011).to_s(2) == ("-" + (~0b01111011).abs.to_s(2)) #
这是一个用于“邀请您的 friend 加入此群组”脚本的快速 SQL 查询。 我有 2 个表:users 和 group_members。我正在尝试执行一个查询,选择我所有的 friend ——由第一
负 ASCII 值有什么意义? int a = '«'; //a = -85 but as in ASCII table '<<' should be 174 最佳答案 没有负数ASCII值。 ASC
我知道用 PHP 可以做到这一点,但是有没有办法只用 MySQL 来做到这一点? 我有这个数据库: --------------------------------------------------
我在变量中有一个时间戳 $data = (float) -2208988800; 是否可以根据这些数据创建正确的日期?date("d.M.Y", $data) 返回“07.02.2036” 最佳答案
你好我如何将括号格式的负值转换为 double 值。目前我有这个。 Payment.Text = Calc_Payment().ToString("#,##0.00;(#,##0.00)"); 将支付
这是一个小程序。这应该打印 0 或 1,还是它有未定义的行为? #include struct S0 { unsigned f1 : 1; }; struct S0 s; int main (v
运行 lgb.cv 时,我有时会从日志中看到“从分数开始训练”后的负数。想知道这个数字到底是什么意思,单位是什么?是根据参数中指定的指标吗?以下是摘录: [LightGBM] [Info] Total
我正在使用变分自动编码器类型模型,我的损失函数的一部分是均值为 0 和方差为 1 的正态分布与另一个均值和方差由我的模型预测的正态分布之间的 KL 散度。 我用以下方式定义了损失: def kl_lo
Tôi là một lập trình viên xuất sắc, rất giỏi!