[英]How to add and remove individual bits from an ArrayBuffer in JavaScript?
[英]How to add bits in JavaScript
假设您有两个整数10和20。即00001010
和00010100
。 然后,我想将它们基本连接为字符串,但结果是一个新的整数。
00001010 + 00010100 == 0000101000010100
最后的数字是2580
。
但是,我正在寻找一种无需实际将其转换为字符串的方法。 寻找更有效的方法来对整数本身进行一些调整。 我对此不太熟悉,但我想它会遵循以下原则:
var a = 00001010 // == 10
var b = 00010100 // == 20
var c = a << b // == 2580
注意,我希望它可以处理任何位序列。 因此,即使:
var a = 010101
var b = 01110
var c = a + b == 01010101110
您的基本公式是:
c = b + (a << 8).
这里的窍门是您需要始终移位8。但是由于a
和b
并不总是使用字节中的所有8位,因此JavaScript会自动忽略任何前导零。 我们需要恢复前导零(的数量b
),或尾随零a
,并添加之前在前面加上他们回来。 这样,所有位都保持在正确的位置。 这需要一个这样的方程式:
c = b + (a << s + r)
其中s
是最高设置位在(从右到左去) b
,和r
是比特的剩余数,使得s + r = 8
。
本质上,您要做的就是将第一个操作数a
移8位,以有效地将尾随零添加到a
或相等地说,将前导零填充到第二个操作数b
。 然后,您正常添加。 这可以使用对数来完成,并移位和逐位OR
操作以提供O(1)
对于某个任意的正整数解a
和b
,其中位的数目a
和b
不超过一些正整数n
。 在字节的情况下, n = 8
。
// Bitwise log base 2 in O(1) time
function log2(n) {
// Check if n > 0
let bits = 0;
if (n > 0xffff) {
n >>= 16;
bits = 0x10;
}
if (n > 0xff) {
n >>= 8;
bits |= 0x8;
}
if (n > 0xf) {
n >>= 4;
bits |= 0x4;
}
if (n > 0x3) {
n >>= 2;
bits |= 0x2;
}
if (n > 0x1) {
bits |= 0x1;
}
return bits;
}
// Computes the max set bit
// counting from the right to left starting
// at 0. For 20 (10100) we get bit # 4.
function msb(n) {
n |= n >> 1;
n |= n >> 2;
n |= n >> 4;
n |= n >> 8;
n |= n >> 16;
n = n + 1;
// We take the log here because
// n would otherwise be the largest
// magnitude of base 2. So, for 20,
// n+1 would be 16. Which, to
// find the number of bits to shift, we must
// take the log base 2
return log2(n >> 1);
}
// Operands
let a = 0b00001010 // 10
let b = 0b00010100 // 20
// Max number of bits in
// in binary number
let n = 8
// Max set bit is the 16 bit, which is in position
// 4. We will need to pad 4 more zeros
let s = msb(b)
// How many zeros to pad on the left
// 8 - 4 = 4
let r = Math.abs(n - s)
// Shift a over by the computed
// number of bits including padded zeros
let c = b + (a << s + r)
console.log(c)
输出:
2580
笔记:
参考文献:
所以问题是:
a是10(二进制0000 1010)
b为20(二进制0100 0100)
您想以某种方式获得2580的位移。
如果您使用a << = 8将a右移8(这与将a乘2 ^ 8相同),则会得到
1010 0000 0000与10 * 2 ^ 8 = 2560相同。
由于a的低位全为0(当您使用<<时,它用0填充新位),您可以在其顶部加上b 1010 0000 0000 + 0100 0100,得到1010 0001 0100。
所以在1行代码中,它是var result = a<<8 + b
。
请记住,在编程语言中,大多数语言都没有针对“二进制”的显式内置类型。 但是一切本质都是二进制的。 所以int是一个“二进制”,一个对象是“二进制” ..etc。 当您要对某些数据执行一些二进制操作时,可以仅使用具有二进制操作数的数据类型。
这是一个更通用的版本,说明如何在不使用字符串操作和数据的情况下连接两个数字的二进制表示形式
/* This function concate b to the end of a and put 0's in between them. b will be treated starting with it's first 1 as its most significant bit b needs to be bigger than 0, otherwise, Math.log2 will give -Infinity for 0 and NaN for negative b padding is the number of 0's to add at the end of a */ function concate_bits(a, b, padding) { //add the padding 0's to a a <<= padding; //this gets the largest power of 2 var power_of_2 = Math.floor(Math.log2(b)); var power_of_2_value; while (power_of_2 >= 0) { power_of_2_value = 2 ** power_of_2; a <<= 1; if (b >= power_of_2_value) { a += 1; b -= power_of_2_value; } power_of_2--; } return a; } //this will print 2580 as the result let result = concate_bits(10, 20, 3); console.log(result);
注意,我希望它可以处理任何位序列。 因此,即使:
var a = 010101
var b = 01110
var c = a + b == 01010101110
除非您转换为字符串或以其他方式在每个数字中存储位数,否则这是不可能的。 10101
010101
0010101
等都是相同的数字(21),一旦将其转换为数字,就无法判断该数字最初有多少个前导零。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.