在JavaScript代码中,字节的8位表示8个布尔“决策”(又名:标志),需要隔离每个给定位以转换为布尔变量。考虑一下我使用字符串解析的解决方案:
var bitParser = function (_nTestByte, _nBitOrdinal) {
var bits = ("00000000" + _nTestByte.toString(2)).slice(-8); // convert to binary and zero-pad
return bits[_nBitOrdinal] === "1";
};
console.log(bitParser(0b10100101, 2)); // ECMAScript 6+ prefix, returns true它可以工作,并显示所需的结果。然而,我有一个假设,即一点移位技术比字符串操作更快。我倾向于相信这一点,但却渴望证明这一点。
问题是,我还没有产生这样一个正确工作的函数,更不用说我可以测试的东西了。我创建了以下逻辑计划,我认为这是正确的:
/*
LOGIC PLAN
----------
0) Remember: all bitwise operators return 32 bits even though we are using 8
1) Left shift until the desired bit is the left-most (highest) position;
2) Right shift (zero filling) 31 bits to eliminate all right bits
*/登录计划的实现如下。由于位运算符的32位性质,我认为必须先移除整个左3字节(24位),然后才能到达正在处理的字节。然后,假设左边的第三个位(字符串序数2)是所需的位,我将移出另外两个位(序数0& 1),总共是26位左移位。
这应该会产生一个二进制数,其馀所有的位都是所需的,后面跟着31个不需要的零字节。向右移动这31位将产生一个二进制,其中31 (现在)引导零位,其计算值为所需位的值。当然,如果这是真的,我就不会写这个问题了,现在我会写吗?
// hardcoded, assuming the second "1" (ordinal 2) is the bit to be examined
console.log((0b10100101 << 26) >> 31); // instead of 1, returns -1我觉得我真的很接近,但是错过了一些东西,或者把JavaScript推得太紧了(lol)。
发布于 2017-01-09 12:55:06
在JavaScript代码中,字节的8位表示8个布尔“决策”(又名:标志),需要隔离每个给定位以转换为布尔变量.
如果这是实际目标,那么位移法既没有必要也没有用处:只需使用按位的&和所需的位,这将为您提供0或设置了该位的数字。0是虚假的,有位设置的数字是真实的。您可以按原样使用,也可以通过!!flag或Boolean(flag)强制使用布尔值。
下面是使用位掩蔽的bitParser函数:
var bitParser = function (_nTestByte, _nBitOrdinal) {
return !!(_nTestByte & Math.pow(2, _nBitOrdinal));
};
console.log(bitParser(0b10100101, 2)); // true
console.log(bitParser(0b10100101, 1)); // false
当然,与其每次执行Math.pow,不如使用一个查找表:
var bits = [
0b00000001,
0b00000010,
0b00000100,
0b00001000,
0b00010000,
0b00100000,
0b01000000,
0b10000000
];
var bitParser = function (_nTestByte, _nBitOrdinal) {
return !!(_nTestByte & bits[_nBitOrdinal]);
};
console.log(bitParser(0b10100101, 2)); // true
console.log(bitParser(0b10100101, 1)); // false
发布于 2017-01-09 14:28:56
是的,它可以,而且你所做的几乎是正确的。
整数表示为32位二进制数,最左边的位表示符号(如果数字为负数,则为1,如果数字为正,则为0 )。让我们来看看其中一些数字的表示:
//last 31 digits keeps increasing as the number decreases
// ...
-2 => 0b11111111111111111111111111111110
-1 => 0b11111111111111111111111111111111
0 => 0b00000000000000000000000000000000
1 => 0b00000000000000000000000000000001
2 => 0b00000000000000000000000000000010
// ...
// last 31 digits keep increasing as the number increases现在,您所拥有的(0b10100101 << 26)应该为您提供10010100000000000000000000000000,您希望它是一个很大的负数(因为最左边的是1)。然后,你就有了>> 31,你期望它能去掉所有的31位,然后留给你最左边的部分。
这应该有效,但不是发生了什么。为什么会这样呢?这是因为想出ECMAScript的人认为如果4 >> 1返回2,-4 >> 1返回-2会更有意义。
4 >> 1 // returns 2 which is 0b00000000000000000000000000000010
0b0000000000000000000000000000000100 >> 1 // returns 2, same
-4 >> 1 // returns -2, which is 0b11111111111111111111111111111110但是-4是0b11111111111111111111111111111100,为了您的目的,将其右移1会产生0b01111111111111111111111111111110 (大正数,因为左后位是0),这不是-2!
为了克服这个问题,您可以使用另一个右移位操作符,它不关心符号:>>>。-4 >>> 1是2147483646,这就是我们想要的。
所以console.log((0b10100101 << 26) >>> 31);给了你1,这就是你想要的。您还可以继续使用>>,并将任何负面结果视为选择1的结果。
发布于 2017-01-09 12:53:51
实现实际需要的最简单方法是使用简单的条件,而不是试图隔离位数。
var bitParser = function (_nTestByte, _nBitOrdinal) {
return (_nTestByte & _nBitOrdinal);
};
console.log(bitParser(6, 2) ? true : false); // true
console.log(bitParser(6, 1) ? true : false); // false
我以一种看似复杂的方式修改了console.log()表达式。
这只是在这个步骤中真正显示逻辑结果,而我并没有选择在函数中使用!!,所以返回一个真正的/falsy值,而不是返回true\false。
实际上,这种方法保持了所有最简单的可能,因为代码中的预期使用if (bitParser(...))会自动将结果转换为布尔值。
顺便说一句,不管_nTestByte大小多大(可能超过1字节),它都能工作。
https://stackoverflow.com/questions/41548443
复制相似问题