为啥 ~-1 等于 0 而 ~1 等于 -2?

Posted

技术标签:

【中文标题】为啥 ~-1 等于 0 而 ~1 等于 -2?【英文标题】:Why does ~-1 equal 0 and ~1 equal -2?为什么 ~-1 等于 0 而 ~1 等于 -2? 【发布时间】:2013-08-17 22:35:58 【问题描述】:

根据 ECMAScript 5.1 标准的 11.4.8 小节:

产生式 UnaryExpression : ~ UnaryExpression 评估如下:

    expr 成为评估UnaryExpression的结果。 让oldValue 成为ToInt32(GetValue(expr))。 将按位补码的结果返回到oldValue。结果是一个带符号的 32 位整数。

~ 运算符将调用内部方法ToInt32。据我了解,ToInt32(1)ToInt32(-1) 将返回相同的值 1 ,但为什么 ~-1 等于 0 和 ~1 等于 -2?

现在我的问题是为什么ToInt32(-1) 等于-1? ECMAScript 5.1 标准的9.5 小节:

抽象操作 ToInt32 将其参数转换为 232 个整数值之一 在 -231 到 231-1 的范围内,包括端点。这个抽象操作的作用是 如下:

    令 number 为对输入参数调用 ToNumber 的结果。 如果数字是 NaN、+0、-0、+∞ 或 -∞,则返回 +0。 让 posInt 为 sign(number) * floor(abs(number))。 令 int32bit 为 posInt 模 232;即 Number 的有限整数值 k 输入正号且幅度小于 232 使得数学 posInt 和 k 的差在数学上是 232 的整数倍。 如果int32bit大于等于231,返回int32bit-232,否则 返回 int32bit。

当参数为-1时,根据9.5, 在步骤 1 数字仍然是-1, 跳过步骤 2 在步骤 3 posInt 将为 -1 在第 4 步 int32bit 将为 1 在第 5 步中,它将返回 1

哪一步错了?

【问题讨论】:

ToIn32(-1) 应该根据ecma-international.org/ecma-262/5.1/#sec-9.5产生-1 您的理解是错误的,在您之前的问题中已得到纠正...(更具体地说,在我的回答中) what is the result of 'x modulo y'?的可能重复 在查找有关波浪号的信息时发现这很有帮助。 javascriptturnsmeon.com/the-tilde-operator-in-javascript。基本上~x === -(x + 1) 【参考方案1】:

-1 32 位整数

1111 1111 1111 1111 1111 1111 1111 1111

所以~-1 将是

0000 0000 0000 0000 0000 0000 0000 0000

这是零。

1 32 位整数

0000 0000 0000 0000 0000 0000 0000 0001

所以~1 将是

1111 1111 1111 1111 1111 1111 1111 1110

这是-2

您应该阅读two's complement 以了解以二进制为基础的负整数的显示。

【讨论】:

感谢您显示我的错误,我只是想念输入这个值。它是固定的。【参考方案2】:

您从哪里得知ToInt32(-1) 的计算结果为 1?它的计算结果为 -1,在 32 位二进制补码表示中,所有位都设置为 1。当您应用 ~ 运算符时,每个位都变为 0,这是 0 在 32 位中的表示,二进制补码。

1 的表示是除了位 0 之外的所有位 0。当位反转时,结果是除了位 0 之外的所有位 1。这恰好是 -2 的二进制补码表示。 (要看到这一点,只需从 -1 的二进制补码表示中减去 1。)

【讨论】:

【参考方案3】: ToInt32(1) 将返回 1 ToInt32(-1) 将返回 -1 -1 通过设置所有 32 位表示为带符号的 32 位整数。其按位补码全部清除,因此~-1 产生0 1 表示为一个带符号的 32 位整数,除底部位外,所有位都被清除。它的按位补码设置了除底部位之外的所有位,底部位是值-2 的有符号32 位整数表示。因此,~1 产生 -2

【讨论】:

以上是关于为啥 ~-1 等于 0 而 ~1 等于 -2?的主要内容,如果未能解决你的问题,请参考以下文章

为啥分割模型库的预测输出(值)是(0到1)而不是(0或1)?

为啥 Lua 数组(表)从 1 而不是 0 开始?

在servicestack中使用protobuf,为啥order只能从1而不是0开始?

为啥 Stack 使用基于 1 的索引而不是 Java 中的 Array 中的基于 0 的索引?

为啥只有数组的第一个元素被初始化为-1?而其余的都是0 [重复]

在 JDBC 中,为啥准备好的语句的参数索引从 1 而不是 0 开始?