【问题标题】:bit shift vs multiplication位移与乘法
【发布时间】:2013-12-13 23:48:51
【问题描述】:

我正在尝试将字节数组转换为数字,对于大数字, 我看到位移给出了 -ve 结果。 你们当中有人可以请我们为什么看到这个问题吗?你觉得使用“乘法”而不是“位移”有什么缺点吗?

例如,

<script language="JavaScript">
    var myVar = 1000000;
    document.write("Bit shift Result: " + (myVar << 8));
    document.write("<br>");
    document.write("Multiplication Result: " + parseInt(myVar *256));
</script>

输出:

位移结果:256000000

乘法结果:256000000

向 myVar 添加一个零后,您会看到我正在谈论的问题

<script language="JavaScript">
    var myVar = 10000000;
    document.write("Bit shift Result: " + (myVar << 8));
    document.write("<br>");
    document.write("Multiplication Result: " + parseInt(myVar *256));
</script>

输出:
位移结果:-1734967296

乘法结果:2560000000

【问题讨论】:

  • 总结答案:这是因为 JavaScript 很糟糕。它是制度化的疯狂——例如,特定的疯狂、明确定义的疯狂、彻底记录的疯狂。
  • @Claudiu 我不知道你在说什么,你在其他编程语言(Java、C#、C 等)中也会得到类似的结果。
  • @BenjaminGruenbaum:我的意思是所有 JavaScript 数字都是 doubles,但在某些情况下它们的行为就像 int32 一样,只是为了它的见鬼。如果您在 C 中对 double 进行位移,它会,嗯..位移位。这不是这里的情况。另外,我的评论还提到了其他一些古怪的东西,比如所有数组索引实际上都是字符串,如果它们可以转换为整数,则充当数组中的整数,但如果不是,则充当属性。很棒的东西,而且都在规范中。
  • @Claudiu 对,因为打字是基于 JavaScript 中的行为。在可能的情况下,内部引擎使用实际的 C 类数组(或 32 位整数),并且作为开发人员,您不必担心它。您的开发经验与 C、Java、C# 或 Python 没有什么不同。我确实同意该语言很容易弄乱它(例如将“名称”之类的键添加到数组中),但这并不意味着任何人都应该/会这样做:)所有“不一致”都在规范中原因,而这个原因不仅仅是“定义明确”或符合规范。

标签: javascript bit-shift multiplication


【解决方案1】:

回答您的两个问题:

请问我们为什么会看到这个问题?

JavaScript 数字是标准的 IEEE 双精度数。

JavaScript 可以容纳的最大整数值为:9007199254740992

但是,移位运算符适用于 32 位整数。

我引用the language specification:

5 .令 lnum 为 ToInt32(lval)。

...

返回对 lnum 执行符号扩展右移 shiftCount 位的结果。传播最高有效位。结果是一个带符号的 32 位整数。

您认为使用“乘法”而不是“位移”有什么缺点吗?

它仍然有点慢,但你真的应该避免在大多数时间直接在 JavaScript 中处理非常大的数字。

有些库可以处理非常大的数字,并且正在讨论一些功能,以便为语言(ES7 值类型)添加对大数字的更好支持。

【讨论】:

  • @user2864740 怎么样:我实际上已经阅读了在不同 JavaScript 引擎中实现此逻辑的代码,以及它当前在 v8 中实现的方式 较慢(至少在最初)。你有足够的理由吗?
  • 技术上这不是真的:“JavaScript 可以容纳的最大整数值是:9007199254740992”它可以精确地容纳 9007199254740994、9007199254740996 等以及许多其他更大的整数。我通常表述这个想法的方式是 9007199254740993 是 JavaScript 不能 持有的最小正整数。
  • @Matt 在这里 - 这是我在 JavaScript 中持有一个带有 1000 个零的数字作为搅拌:“1e1000” - 我的意思是 9007199254740992 是您可以持有的最大数字而不必担心关于精度,你可以在 JS 中存储的最大数字是179769313486232000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
  • 当然 - 我知道潜在的问题对我们双方来说都是透明的,而且我很清楚你的意思。我只是想找到最好的方式向其他读者表达这些想法,既简洁又准确..
  • 非常感谢本杰明
【解决方案2】:

在 JavaScript 中,所有位运算符首先在操作数上调用 [ToInt32]。这包括移位运算符。

然后位运算符(即&lt;&lt;)对有符号 two's-complement 32 位整数起作用。移位后产生的位模式表示一个负数。

00000000 10011000 10010110 10000000 - original value, after [ToInt32], as bits
10011000 10010110 10000000 00000000 - value after shift; a negative bit pattern

除非需要这种行为,否则我会使用乘法。

(当然,如果写一个PC emulator,那么每一个小技巧都很重要......但更喜欢乘法。)

【讨论】:

  • 非常感谢;这是一个超快的反应。
【解决方案3】:

在内部,JavaScript 使用 64 位浮点数和 52 位尾数来表示所有数字。但是,您也可以进行位运算,但只能作为带符号的 32 位整数,从 -2147483648 到 +2147483647。要超出此范围,您必须使用常规算术,而不是位运算。

【讨论】:

    猜你喜欢
    • 2012-01-05
    • 2014-08-05
    • 2020-01-28
    • 1970-01-01
    • 2016-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-12
    相关资源
    最近更新 更多