java+script数值计算_ECMAScript - 运算成分

按位操作符(Bitwise operators) 将其操作数(operands)当作32位的比特序列(由0和1组成),而不是十进制、十六进制或八进制数值。例如,十进制数9,用二进制表示则为1001。按位操作符操作数字的二进制形式,但是返回值依然是标准的 JavaScript 数值。

下面的表格总结了JavaScript中的按位操作符:运算符用法描述

a & b对于每一个比特位,只有两个操作数相应的比特位都是1时,结果才为1,否则为0。

a | b对于每一个比特位,当两个操作数相应的比特位至少有一个1时,结果为1,否则为0。

a ^ b对于每一个比特位,当两个操作数相应的比特位有且只有一个1时,结果为1,否则为0。

~ a反转操作数的比特位,即0变成1,1变成0。

a << b将 a 的二进制形式向左移 b (< 32) 比特位,右边用0填充。

a >> b将 a 的二进制表示向右移b (< 32) 位,丢弃被移出的位。

a >>> b将 a 的二进制表示向右移b (< 32) 位,丢弃被移出的位,并使用 0 在左侧填充。

有符号32位整数

所有的按位操作符的操作数都会被转成补码(two's complement)形式的有符号32位整数。补码形式是指一个数的负对应值(negative counterpart)(如 5和-5)为数值的所有比特位反转后,再加1。反转比特位即该数值进行’非‘位运算,也即该数值的反码。例如下面为整数314的二进制编码:

下面编码 ~314,即 314 的反码:

最后,下面编码 -314,即 314 的补码:

补码保证了当一个数是正数时,其最左的比特位是0,当一个数是负数时,其最左的比特位是1。因此,最左边的比特位被称为符号位(sign bit)。

0 是所有比特数字0组成的整数。

-1 是所有比特数字1组成的整数。

-2147483648(十六进制形式:-0x80000000)是除了最左边为1外,其他比特位都为0的整数。

2147483647(十六进制形式:0x7fffffff)是除了最左边为0外,其他比特位都为1的整数。

数字-2147483648 和 2147483647 是32位有符号数字所能表示的最小和最大整数。

按位逻辑运算符

Bitwise logical operators

从概念上讲,按位逻辑操作符遵守下面规则:操作数被转换成32位整数,用比特序列(0和1组成)表示。若超過32bits,則取低位32bit,如下所示:

Before: 11100110111110100000000000000110000000000001

After: 10100000000000000110000000000001第一个操作数的每个比特位与第二个操作数的相应比特位匹配:第一位对应第一位,第二位对应第二位,以此类推。

位运算符应用到每对比特位,最终的运算结果由每一对“位”的运算结果组合起来。

& (按位与)

对每对比特位执行与(AND)操作。只有 a 和 b 都是 1 时,a AND b 才是 1。与操作的真值表如下:aba AND b

000

010

100

111

将任一数值 x 与 0 执行按位与操作,其结果都为 0。将任一数值 x 与 -1 执行按位与操作,其结果都为 x。

| (按位或)

对每一对比特位执行或(OR)操作。如果 a 或 b 为 1,则 a OR b 结果为 1。或操作的真值表:aba OR b

000

011

101

111

将任一数值 x 与 0 进行按位或操作,其结果都是 x。将任一数值 x 与 -1 进行按位或操作,其结果都为 -1。

^ (按位异或)

对每一对比特位执行异或(XOR)操作。当 a 和 b 不相同时,a XOR b 的结果为 1。异或操作真值表:aba XOR b

000

011

101

110

将任一数值 x 与 0 进行异或操作,其结果为 x。将任一数值 x 与 -1 进行异或操作,其结果为 ~x。

~ (按位非)

对每一个比特位执行非(NOT)操作。NOT a 结果为 a 的反转(即反码)。非操作的真值表:aNOT a

01

10

对任一数值 x 进行按位非操作的结果为 -(x + 1)。例如,~5 结果为 -6。

与 indexOf 一起使用示例:

按位移动运算符

Bitwise shift operators

移位运算符带两个操作数:第一个是待移位的数, 第二个是指定第一个数要被移多少位的数. 移位的方向由运算符来控制.

移位运算符把操作数转为32bit整数,然后得出一个与待移位数相同种类的值。

按位移动会先将操作数转换为大端 (big-endian) 表示的 32位整数; and return a result of the same type as the left operand (?)。右操作数应当小于 32位,否则只有最低 5 个字节会被使用。

移位运算符列表如下运算符描述范例<<

(左移位)将第一个操作数向左移动指定数量的位. 左边移出位被抛弃. 左边移出的几位被丢弃.右边多出的空位由0补齐9<<2产生36,因为1001移位2比特向左变为100100,它是36。

>>

(带符号右移)将第一个操作数向右移动指定数量的位. 右边移出位被抛弃. 左边多出的空位由原值的最左边数字补齐.9>>2产生2,因为1001移位2位向右变为10,其是2。同样,-9>>2产生-3,由于符号被保留。

>>>

(补零右移)将第一个操作数向右移动指定数量的位. 右边移出位被抛弃. 左边多出的空位由0补齐.19>>>2产生4,因为10011移位2位向右变为100,它是4。对非负数值,补零右移和带符号右移产生相同结果。

<< (左移)

该操作符会将第一个操作数向左移动指定的位数。向左被移出的位被丢弃,右侧用 0 补充。

For example, 9 << 2 yields 36:

在数字 x 上左移 y 比特得到 x * 2y.

>> (有符号右移)

该操作符会将第一个操作数向右移动指定的位数。向右被移出的位被丢弃,拷贝最左侧的位以填充左侧。由于新的最左侧的位总是和以前相同,符号位没有被改变。所以被称作“符号传播”。

例如, 9 >> 2 得到 2:

相比之下, -9 >> 2 得到 -3,因为符号被保留了。

>>> (无符号右移)

该操作符会将第一个操作数向右移动指定的位数。向右被移出的位被丢弃,左侧用0填充。因为符号位变成了 0,所以结果总是非负的。(译注:即便右移 0 个比特,结果也是非负的。)

对于非负数,有符号右移和无符号右移总是返回相同的结果。例如, 9 >>> 2 得到 2 和 9 >> 2 相同:

但是对于负数却不尽相同。 -9 >>> 2 产生 1073741821 这和 -9 >> 2 不同:

标志位与掩码

位运算经常被用来创建、处理以及读取标志位序列——一种类似二进制的变量。虽然可以使用变量代替标志位序列,但是这样可以节省内存(1/32)。

例如,有 4 个标志位:标志位 A:我们有 ant

标志位 B:我们有 bat

标志位 C:我们有 cat

标志位 D:我们有 duck

标志位通过位序列 DCBA 来表示。当一个位被置位 (set) 时,它的值为 1 。当被清除 (clear) 时,它的值为 0 。例如一个变量 flags 的二进制值为 0101:

这个值表示:标志位 A 是 true (我们有 ant);

标志位 B 是 false (我们没有 bat);

标志位 C 是 true (我们有 cat);

标志位 D 是 false (我们没有 duck);

因为位运算是 32 位的, 0101 实际上是 00000000000000000000000000000101。因为前面多余的 0 没有任何意义,所以他们可以被忽略。

掩码 (bitmask) 是一个通过与/或来读取标志位的位序列。典型的定义每个标志位的原语掩码如下:

新的掩码可以在以上掩码上使用逻辑运算创建。例如,掩码 1011 可以通过 FLAG_A、FLAG_B 和 FLAG_D 逻辑或得到:

某个特定的位可以通过与掩码做逻辑与运算得到,通过与掩码的与运算可以去掉无关的位,得到特定的位。例如,掩码 0100 可以用来检查标志位 C 是否被置位:

一个有多个位被置位的掩码表达任一/或者的含义。例如,以下两个表达是等价的:

可以通过与掩码做或运算设置标志位,掩码中为 1 的位可以设置对应的位。例如掩码 1100 可用来设置位 C 和 D:

可以通过与掩码做与运算清除标志位,掩码中为 0 的位可以设置对应的位。掩码可以通过对原语掩码做非运算得到。例如,掩码 1010 可以用来清除标志位 A 和 C :

如上的掩码同样可以通过 ~FLAG_A & ~FLAG_C 得到(德摩根定律):

标志位可以使用异或运算切换。所有值为 1 的为可以切换对应的位。例如,掩码 0110 可以用来切换标志位 B 和 C:

最后,所有标志位可以通过非运算翻转:

转换片段

将一个二进制数的 String 转换为十进制的 Number:

将一个十进制的 Number 转换为二进制数的 String:

自动化掩码创建

如果你需要从一系列的 Boolean 值创建一个掩码,你可以:

逆算法:从掩码得到布尔数组

如果你希望从掩码得到得到 Boolean Array :

你可以同时测试以上两个算法……

仅仅由于教学目的 (因为有 Number.toString(2) 方法),我们展示如何修改 arrayFromMask 算法通过 Number 返回二进制的 String,而非 Boolean Array:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值