相比之下, -9 >> 2 得到 -3,因为符号被保留了。
-9 (base 10): 11111111111111111111111111110111 (base 2) -------------------------------- -9 >> 2 (base 10): 11111111111111111111111111111101 (base 2) = -3 (base 10)与左移相反,右移一位在原数字基础上除以2
64 >> 1 // 32 无符号右移将 a 的二进制表示向右移 b (< 32) 位,丢弃被移出的位,并使用 0 在左侧填充。
用法: a >>> b
在非负数来说, 9 >>>2 和 9 >> 2 都是一样的结果
9 (base 10): 00000000000000000000000000001001 (base 2) -------------------------------- 9 >>> 2 (base 10): 00000000000000000000000000000010 (base 2) = 2 (base 10)而对于负数来说,结果就大有不同了,因为 >>> 不保留符号,当负数无符号右移时,会使用0填充
-9 (base 10): 11111111111111111111111111110111 (base 2) -------------------------------- -9 >>> 2 (base 10): 00111111111111111111111111111101 (base 2) = 1073741821 (base 10)可以使用无符号右移来判断一个数的正负
function isPos(n) { return (n === (n >>> 0)) ? true : false; } isPos(-1); // false isPos(1); // true虽然 -1 >>> 0 不会发生右移,但 -1 的二进制码已经变成了正数的二进制码, -1 >>> 0 结果为4294967295
Javascript进制转换 toStringtoString 常用于将一个变量转为字符串,或是判断一个变量的类型,例如:
let arr = [] Object.prototype.toString.call(arr) // [object Array]你应该没想过 toString 可以用于进制转换,请看下面例子:
(18).toString(2) // 10010(base 2) (18).toString(8) // 22 (base 8) (18).toString(16) // 12 (base 16)参数规定表示数字的基数,是 2 ~ 36 之间的整数,若省略该参数,则使用基数 10。该参数可以理解为转换后的进制表示。
parseIntparseInt 常用于数字取整,它同样可以传入参数用于进制转换,请看下面例子:
parseInt(10010, 2) // 18 (base 10) parseInt(22, 8) // 18 (base 10) parseInt(12, 16) // 18 (base 10)第二个参数表示要解析的数字的基数,该值介于 2 ~ 36 之间。如果省略该参数或其值为 0,则数字将以 10 为基础来解析。如果该参数小于 2 或者大于 36,则 parseInt 将返回 NaN。
记得有道面试题是这样的:
// 问:返回的结果 [1, 2, 3].map(paseInt)接下来,我们来一步一步的看下过程发生了什么?
parseInt(1, 0) // 基数为 0 时,以 10 为基数进行解析,结果为 1 parseInt(2, 1) // 基数不符合 2 ~ 36 的范围,结果为 NaN parseInt(3, 2) // 这里以 2 为基数进行解析,但 3 很明显不是一个二进制表示,故结果为 NaN //题目结果为 [1, NaN, NaN] 手动实现进制转换虽然 JavaScript 为我们内置了进制转换的函数,但手动实现进制转换有利于我们理解过程,提高逻辑能力。对于初学者来说也是一个很不错的练习例子。以下只简单实现非负整数的转换。
十进制转二进制基于 “除二取余” 思路实现
function toBinary(value) { if (isNaN(Number(value))) { throw `${value} is not a number` } let bits = [] while (value >= 1) { bits.unshift(value % 2) value = Math.floor(value / 2) } return bits.join('') }使用
toBinary(36) // 100100 toBinary(12) // 1100 二进制转十进制基于 “按权相加” 思路实现
function toDecimal(value) { let bits = value.toString().split('') let res = 0 while (bits.length) { let bit = bits.shift() if (bit == 1) { // ** 为幂运算符,如:2**3 为 8 res += 2 ** bits.length } } return res }使用
toDecimal(10011) // 19 toDecimal(11111) // 33 写在最后本文为大家介绍了进制和位运算的相关知识,旨在温故知新。我们只需要大概了解就好,因为在开发中真的用得少,至少我只用过 ~~ 来取整。而类似于~~这种取整操作还是尽量少用为好,对于其他开发者来说,可能会影响到代码可读性。