【问题标题】:Bitwise operations on strings in javascriptjavascript中字符串的按位运算
【发布时间】:2014-04-08 08:35:33
【问题描述】:

在 javascript 中,以下字符到字符二进制操作的测试打印 0 676 次:

var s = 'abcdefghijklmnopqrstuvwxyz';
var i, j;
for(i=0; i<s.length;i++){ for(j=0; j<s.length;j++){ console.log(s[i] | s[j]) }};

如果 js 使用的是字符串的实际二进制表示,我希望这里有一些非零值。

同样,测试字符串和整数的二元运算,下面分别打印 26 255s 和 0s。 (选择 255 是因为它是二进制的 11111111)。

var s = 'abcdefghijklmnopqrstuvwxyz';
var i; for(i=0; i<s.length;i++){ console.log(s[i] | 255) }
var i; for(i=0; i<s.length;i++){ console.log(s[i] & 255) }

javascript 在这里做什么?似乎javascript在二进制操作之前将任何字符串转换为false

备注

如果你在 python 中尝试这个,它会抛出一个错误:

>>> s = 'abcdefghijklmnopqrstuvwxyz'
>>> [c1 | c2 for c2 in s for c1 in s]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for |: 'str' and 'str'

但是像这样的东西似乎work in php

【问题讨论】:

  • 规范将解释转换。 es5.github.io/#x11.10具体toInt32()转换在这里:es5.github.io/#x9.5
  • 谢谢@cookie-monster。该注释源非常清楚地表明,在隐式类型转换中toNumber 产生NaN,然后在NaN 上调用ToInt32 产生+0

标签: javascript binary


【解决方案1】:

在 JavaScript 中,当字符串与二元运算符一起使用时,它首先被转换为数字。下面显示了 ECMAScript 规范的相关部分,以解释其工作原理。

Bitwise operators:

产生式 A : A @ B,其中 @ 是上述产生式中的位运算符之一,计算如下:

  1. 令 lref 为评估 A 的结果。
  2. 设 lval 为 GetValue(lref)。
  3. 令 rref 为评估 B 的结果。
  4. 设 rval 为 GetValue(rref)。
  5. 令 lnum 为 ToInt32(lval)。
  6. 设 rnum 为 ToInt32(rval)。
  7. 返回将按位运算符 @ 应用于 lnum 和 rnum 的结果。结果是一个带符号的 32 位整数。

ToInt32:

抽象操作 ToInt32 将其参数转换为范围 -231 到 231-1(含)的 232 个整数值之一。这个抽象操作的作用如下:

  1. 让 number 为对输入参数调用 ToNumber 的结果。
  2. 如果数字是 NaN、+0、-0、+∞ 或 -∞,则返回 +0。
  3. 让 posInt 为符号(数字)* 楼层(绝对值(数字))。
  4. 令 int32bit 为 posInt 模 232;即,具有正号且幅度小于 232 的 Number 类型的有限整数值 k,使得 posInt 和 k 的数学差在数学上是 232 的整数倍支持>。
  5. 如果 int32bit 大于等于 231,则返回 int32bit − 232,否则返回 int32bit。

内部 ToNumber 函数将为任何无法解析为数字的字符串返回 NaN,而 ToInt32(NaN) 将给出 0。因此,在您的代码示例中,所有以字母作为操作数的位运算符都将计算为 @987654326 @,这就解释了为什么只打印 0。

请注意,'7' | '8' 之类的值将计算为 7 | 8,因为在这种情况下,用作操作数的字符串可以成功转换为数字。

至于 Python 中的行为为何不同,Python 中实际上并没有任何隐式类型转换,因此对于任何未实现二元运算符的类型(通过使用 __or____and__等),而字符串不实现这些二元运算符。

Perl 做了一些完全不同的事情,bitwise operators are implemented for strings,它本质上会对每个字符串中的相应字节执行按位运算符。

如果您想使用 JavaScript 并获得与 Perl 相同的结果,您需要先使用 str.charCodeAt 将字符转换为其代码点,对结果整数执行按位运算符,然后使用 String.fromCodePoint 将将生成的数值转换为字符。

【讨论】:

  • 谢谢@F.J。这正是我所希望的详细程度。
  • BTW - 这个问题的原因是我在我们的代码库中发现有人使用|= 进行输入验证。当我第一次查看代码时,它们看起来像是在对字符串进行操作,我很好奇它是如何工作的。
【解决方案2】:

如果 JavaScript 对非数字字符串进行按位运算并产生任何有意义的东西,我会感到惊讶。我想,因为 JavaScript 中的任何按位运算符都将其操作数转换为 32 位整数,所以它会将所有非数字字符串简单地转换为 0

我会用...

"a".charCodeAt(0) & 0xFF

这会产生97,即“a”的 ASCII 码,这是正确的,因为它被一个设置了所有位的字节所掩盖。

请记住,因为在其他语言中可以很好地工作,所以在 JavaScript 中并非总是如此。我们谈论的是一种在很短的时间内构思和实施的语言。

【讨论】:

  • 感谢亚历克斯的回复。我知道charCodeAt 函数,但不确定simply turn all non-numerical strings into 0 部分。
【解决方案3】:

JavaScript 使用类型强制,当您尝试对字符串执行数字操作时,它可以尝试将字符串自动解析为数字。解析的值是 0 或更可能是 NaN。这显然不会为您提供您想要获取的信息。

我认为您正在寻找的是charCodeAt,它将允许您获取字符串中字符的数字 Unicode 值以及可能的补充 fromCodePoint,它将数值转换回字符。

【讨论】:

  • 感谢 squid314 的回复。关于字符串值如何被强制类型化的信息正是我所寻找的。​​span>
猜你喜欢
  • 2019-04-21
  • 2011-07-29
  • 2019-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-18
  • 1970-01-01
相关资源
最近更新 更多