JavaScript使用填零运算符(>>>)进行右移会产生意外结果

Javascript#39;s Shift right with zero-fill operator (gt;gt;gt;) yielding unexpected result(JavaScript使用填零运算符(gt;gt;gt;)进行右移会产生意外结果)
本文介绍了JavaScript使用填零运算符(>>>)进行右移会产生意外结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,(-1 >>> 0) === (2**32 - 1),我估计是因为左边加了一个新的零,从而将数字转换成33位数字?

但是,为什么(-1 >>> 32) === (2**32 - 1)也是,而我预计它(将32位数字移位32次并将最高有效位替换为0之后)为0。

它不应该等于((-1 >>> 31) >>> 1) === 0吗?还是我错过了什么?

推荐答案

执行(-1 >>> 0)时,执行的是无符号右移位。这里没有签名的是钥匙。根据spec,>>>的结果始终是无符号的。-1表示为1的two's compliment。以二进制表示的都是1s(在8位系统中应该是11111111)。 所以现在您通过执行>>> 0使其无签名。您的意思是,将-1的二进制表示(全部为1)移位零位(不做任何更改),但使其返回无符号数字。"因此,您将获得所有1的值。请转到浏览器中的任意javascript控制台并键入:

console.log(2**32 - 1) //4294967295
// 0b means binary representation, and it can have a negative sign
console.log(0b11111111111111111111111111111111) //4294967295
console.log(-0b1 >>> 0) //4294967295
记住2 **任何数字减去1都是二进制形式的全一。这和你提升的两个异能的数量是一样的。因此2**32 - 1等于321。例如,2的3次方(8)减去1(7)等于111,表示为二进制。

因此,下一个(-1 >>> 32) === (2**32 - 1).我们来看几件事。我们知道-1的二进制表示形式都是1s。然后将其右移一位,得到的值与所有1都是一样的,但前面加一个零(并返回一个无符号数字)。

console.log(-1 >>> 1) //2147483647
console.log(0b01111111111111111111111111111111) //2147483647

并不断移动,直到末尾有31个零和一个1

console.log(-1 >>> 31) //1

这对我来说很有意义,我们现在32位有31个0和一个1

那么你碰到了奇怪的大小写,再移位一次应该是零对吗?

根据spec:

6.1.6.1.11 Number::unsignedRightShift ( x, y )
Let lnum be ! ToInt32(x).
Let rnum be ! ToUint32(y).
Let shiftCount be the result of masking out all but the least significant 5 bits of rnum, that is, compute rnum & 0x1F.
Return the result of performing a zero-filling right shift of lnum by shiftCount bits. Vacated bits are filled with zero. The result is an unsigned 32-bit integer.

所以我们知道我们已经有了-1,这都是1两句恭维话。我们将按照文档的最后一步将其移位shiftCount位(我们认为是32位)。和shiftCount为:

让ShiftCount为屏蔽除最低有效5位以外的所有rnum的结果,即计算rnum&;0x1F。

那么rnum & 0x1F是什么呢?好的&表示按位AND操作。lnum>>>左边的数字,rnum是它右边的数字。所以我们说32 AND 0x1F。记住,32是1000000x是十六进制,其中每个字符都可以用4位表示。10001,F是1111。因此0x1F0001111111111(31在基数10中,2**5 - 1也是)。

console.log(0x1F) //31 (which is 11111)

  32: 100000 &
0x1F: 011111
     ---------
      000000
如果为零,则为要移位的位数。这是因为32中的前导1不是5最高有效位的一部分!32是6位。所以我们取32个1并将其移位0位!怪不得。答案仍然是321s。

在示例-1 >>> 31中,这是有意义的,因为31是<= 5位。所以我们做了

  31: 11111 &
0x1F: 11111
      -------
      11111

并将其移位31位.不出所料。

让我们进一步测试一下.让我们做

console.log(-1 >>> 33) //2147483647
console.log(-1 >>> 1)  //2147483647

这说得通,只需将其移位一点。

  33: 100001 &
0x1F: 011111
      ---------
      00001
因此,使用按位运算符检查5位会产生混淆。想要和一个没有研究ECMAScript来回答堆栈溢出帖子的人一起玩树桩假人吗?只需问问为什么这些是相同的。

console.log(-1 >>> 24033) //2147483647
console.log(-1 >>> 1)     //2147483647

当然是因为

console.log(0b101110111100001) // 24033 
console.log(0b000000000000001) // 1
//                      ^^^^^ I only care about these bits!!!    

这篇关于JavaScript使用填零运算符(&gt;&gt;&gt;)进行右移会产生意外结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

Update another component when Formik form changes(当Formik表单更改时更新另一个组件)
Formik validation isSubmitting / isValidating not getting set to true(Formik验证正在提交/isValiating未设置为True)
React Validation Max Range Using Formik(使用Formik的Reaction验证最大范围)
Validation using Yup to check string or number length(使用YUP检查字符串或数字长度的验证)
Updating initialValues prop on Formik Form does not update input value(更新Formik表单上的初始值属性不会更新输入值)
password validation with yup and formik(使用YUP和Formick进行密码验证)
10