【问题标题】:Understanding bitwise operations in javascript理解 javascript 中的按位运算
【发布时间】:2010-11-03 11:36:31
【问题描述】:

我目前将数据以二进制形式存储在 XML 文档中,长度为 20 位,每个代表一个布尔值。

<matrix> 

    <resource type="single"> 
        <map>10001010100011110000</map> 
        <name>Resource Title</name> 
        <url>http://www.yoursite.com</url> 
    </resource>

</matrix>

我正在使用 jQuery 解析它,目前正在使用 for 循环和 charAt() 来确定如果值为 == "1" 是否要执行操作。

for (var i = 0; i < _mapLength; i++) {
    if (map.charAt(i) == "1") {
        //perform something here
    }
}

这发生了几次,作为运行缓慢的巨大循环的一部分。有人告诉我,我应该使用按位运算符来处理它,它会运行得更快。

我的问题是:

谁能给我举个例子来说明我如何做到这一点?我试过在线阅读教程,它们似乎就在我头顶上。 (仅供参考:我正计划创建一个 Ruby 脚本,它将我的二进制 0 和 1 转换为我的 XML 中的位。)

或者有没有人知道一个好的、简单的(甚至可能是简化版)教程或可以帮助我掌握这些按位运算符概念的东西?

【问题讨论】:

  • 遗憾的是,如果您/必须/对每个位执行操作,我认为您不会获得太多性能提升。
  • XML 中的二进制让我很伤心。
  • 您可以将该 20 位二进制数存储为更高基数的更紧凑的数字,如果您愿意,仍然可以在 JavaScript 中使用它进行布尔运算。

标签: javascript jquery binary compare bit-manipulation


【解决方案1】:

假设您的位数不超过 32 位,您可以使用 JavaScript 的内置 parseInt() 函数将您的 1 和 0 字符串转换为整数,然后使用 &amp; (and) 运算符测试标志:

var flags = parseInt("10001010100011110000", 2); // base 2

if ( flags & 0x1 )
{
   // do something
}

...

另见:How to check my byte flag?

(问题是在 C 中的使用,但也适用于 JS 中的相同运算符)

【讨论】:

  • 是的,如果你想遍历从右到左的所有位,你可以重复使用“&1”并在每次检查后进行右移。
  • 更准确的说法是“您可以使用 JS 的 parseInt() 将您的字符串转换为 Number”,因为程序员无法访问真正的整数类型。
  • 嗯,严格来说,它始终是一个整数,即使在 base-2 表示 @Null 中!但是,是的,无论您在其中存储什么,数据类型都是浮点数。
【解决方案2】:

单与号(&,与 && 相对)进行逐位比较。但首先您需要使用 parseInt() 将字符串转换为数字。

var map = parseInt("10010", 2); // the 2 tells it to treat the string as binary

var maskForOperation1 = parseInt("10000", 2);
var maskForOperation2 = parseInt("01000", 2);
// ...

if (map & maskForOperation1) { Operation1(); }
if (map & maskForOperation2) { Operation2(); }
// ...

【讨论】:

  • 一个人可能真的会使用var maskForOperation1 = 0x1 &lt;&lt; 4;,并且只更改4 以获取其他掩码(即3 将是maskForOperation2)。
【解决方案3】:

要格外小心。 Javascript 没有整数——数字存储为 64 位浮点数。您应该可以准确地转换为 52 位。如果你得到比这更多的标志,那么当你的“数字”四舍五入到最接近的可表示浮点数时,就会发生不好的事情。 (哎哟!)

此外,按位操作对性能没有帮助,因为浮点数将被转换为整数,经过测试,然后再转换回来。

如果您有几个地方要检查标志,我会在一个对象上设置标志,最好使用名称,如下所示:

var flags = {};
flags.use_apples = map.charAt(4);
flags.use_bananas = map.charAt(10);

等等……

然后您可以在循环中测试这些标志:

if(flags.use_apples) {
    do_apple_thing();
}

对象槽测试将比按位检查更快,因为 Javascript 未针对按位运算符进行优化。但是,如果您的循环很慢,我担心解码这些标志可能不是缓慢的根源。

【讨论】:

  • 不知道为什么人们说 JS 中的按位性能很差。它不是。我已经测试了 JavaScript 按位运算的速度,它们似乎足够快。所做的任何转换似乎都不明显。在最坏的情况下,会有一些偏移和掩蔽。
  • -1 这不太正确,如果所讨论的数字不能转换为有符号的 32 位 int,那么无论如何都会发生坏事,因为 JS 中的按位运算适用于整数,而不是浮点数。而且关于性能的说法是没有根据的。
【解决方案4】:

按位运算符肯定会更快,但只是线性的,而且不会快很多。您可能会节省几毫秒(除非您使用 Javascript 处理大量数据,否则这很可能是个坏主意)。

您应该考虑对循环中的其他代码进行分析,以了解最慢的原因。您还有哪些其他可以使用重构的算法、数据结构和分配?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-04
    • 1970-01-01
    • 2022-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-09
    相关资源
    最近更新 更多