位运算的妙用: 奇偶数, 色值换算,换值, 编码等
位运算的基础知识:
操作数1 & 操作数2
操作数1
和操作数2
转为二进制数,按照第2步进行计算eg: 5.23 | 0 => 5.23 | 0的结果是5
eg: ~9 = -9 -1 = -10
eg: ~~5.5677878 // 5
示例:
- let a = 10
- let b = 20
- a^=b //=> a = b^a => a^b
- b^=a //=> b = a^b => (a^b) ^b => a ^ (b^b) => a ^ 0 => a => 结果是b=a
- a^=b //=> a = b^a => b^b^b ^ (a^a) => b ^ 0 => b =>结果是: a = b
- console.log('a:', a) // 20
- console.log('b:', b) // 10
<<
<< 运算符执行左移位运算。
在移位运算过程中,符号位始终保持不变。
如果右侧空出位置,则自动填充为 0;
超出 32 位的值,则自动丢弃
console.log(5 << 2); // 20
操作数1 << 左移位数
操作数1
转换为二进制数>>
>> 运算符执行有符号右移位运算。
与左移运算操作相反,它把 32 位数字中的所有有效位整体右移,再使用符号位的值填充空位。
移动过程中超出的值将被丢弃。
console.log(1000 >> 8); // 3
操作数1 >> 右移位数
操作数1
转换为二进制数因为计算机很多运算都直接或间接涉及二进制, 所以提一下相关知识:
eg: 将1001.011转换为十进制?
整数部分(从右向左): 1*2^0 + 0*2^1+0*2^2+1*2^3=1+0+0+8=9
小数部分(从左到右): 0*2^-1+1*2^-2+1*2-3=0+1/4+1/8=0+0.25+0.125=0.375
注意: 这里的^不是位移符,是代表数字里的某某次方,比如2^3代表2的3次方
所以1001.011转换为十进制的数字是9.375
比如9.375
整数部分:
9 / 2 => 商4, 余1
4 / 2=> 商2, 余0
2 / 2=> 商1, 余0
1/2=> 商0, 余1
小数部分: 0.375
0.375 * 2 => 0.75 => Math.floor => 0(小于1, 所以继续)
0.75 * 2 => 1.5 => Math.floor => 1(但是余下0.5,继续)
0.5 * 2 => 1 => Math.floor => 1 (如果得到整数1, 没有小数部分就结束)
所以9.375转化为二进制数字是1001.011
parseInt(string, radix)
eg: console.log(parseInt(1010,2)); // 10
如果是小数, 没有现成的方法, 需要代码:
- // 小数部分 => 数字*(2的index次方)
- function eachBinaryDigitPartToDecimal(binaryDigitPartArr) {
- return binaryDigitPartArr.map((currentValue, index) => {
- return Number(currentValue) * Math.pow(2, (-(index + 1)))
- })
- }
- // 如果该二进制只有整数部分则直接用 parseInt(string, radix) 处理
- function eachBinaryIntPartToDecimal(binaryDigit) {
- return parseInt(binaryDigit, 2)
- }
-
- /**
- * 将二进制小数(包含整数部分和小数部分)转换为十进制数
- * @param binaryDigit 二进制数(可能是整数,也可能是小数)
- */
- function floatToDecimal(binaryDigit) {
- // 如果该二进制只有整数部分则直接用 parseInt(string, radix) 处理
- if (Number.isInteger(binaryDigit)) {
- return eachBinaryIntPartToDecimal(binaryDigit)
- } else {
- // 将整数和小数部分的数字分开组成一个数组, 第一个元素是整数部分的数字, 第二个元素是小数部分的数字
- const binaryDigitNumArr = binaryDigit.toString().split(".")
-
- // 将二进制整数转换为十进制数
- const binaryIntParStr = binaryDigitNumArr[0]
- const decimalIntPartNum = eachBinaryIntPartToDecimal(binaryIntParStr)
-
- // 将二进制小数部分转换为十进制数
- const binaryDigitPartArr = binaryDigitNumArr[1].split("") // 将数字split成小数部分的每个数字作为元素的一元数组
- const eachDecimalFloatPartNum = eachBinaryDigitPartToDecimal(binaryDigitPartArr) // 数组的数字变成item * 2^(-index)
- const deciamlFloatPartNum = eachDecimalFloatPartNum.reduce((val, currentVal) => val + currentVal) // 数组元素相加
- return decimalIntPartNum + deciamlFloatPartNum
- }
- }
同理: 十进制转16进制是: 字符串.toString(16)
eg:
const number = 10
console.log(number.toString(2)); // 1010
运用场景:
rgb和16进制颜色相互转换:
- function colorRGBToHex(rgb) {
- // split的参数可以是正则
- const rgbArr= rgb.split(/[^\d]+/)
- // ['', '数字1', '数字2', '数字3', '']
- const color = rgbArr[1] << 16 | rgbArr[2] << 8 | rgbArr[3];
- return `#${color.toString(16)}`
- }
- console.log(colorRGBToHex('rgb(204, 0, 255)'))
-
- // 16进制转rgb格式
- function colorHexToRGB(hex) {
- // 转为6位的16进制, 0x??????
- let newHex = hex.replace('#', '0x'),
- r = newHex >> 16,
- g = newHex >> 8 & 0xff,
- b = newHex & 0xff
- return `rgb(${r},${g},${b})`
- }
- console.log(colorHexToRGB('#CC00FF'))