【问题标题】:"Simulate" a 32-bit integer overflow in JavaScript在 JavaScript 中“模拟”一个 32 位整数溢出
【发布时间】:2014-05-10 06:20:50
【问题描述】:

JavaScript 可以很好地处理以下数学:

var result = (20000000 * 48271) % 0x7FFFFFFF;

但在某些编程语言中,第一次 int*int 乘法会导致值太大而无法保存在标准的 32 位整数中。有没有办法在 JavaScript 中“模拟”这个,看看如果乘法导致整数溢出,结果会是什么?

【问题讨论】:

  • @FélixSaparelli 这不是重复的,20000000 * 48271 仍然在 JavaScript Number 的 52 位精度范围内;它不会溢出。我正在尝试模拟 32 位溢出
  • 我通过从结果中减去 2^32 次来作弊,但我认为这不是非常有效或非常聪明:P
  • if Math.abs(int * int) is greater than (2^32)/2 then log value and continue?

标签: javascript integer-overflow


【解决方案1】:

可以通过“滥用”JavaScript 中可用的按位运算符来模拟 32 位整数(因为它们只能返回该范围内的整数)。

要转换为有符号 32 位整数

x = (a * b) | 0;

要转换为无符号 32 位整数

x = (a * b) >>> 0;

【讨论】:

【解决方案2】:

在较新的浏览器中,Math.imul(a,b) 将为您提供实际的 32 位整数相乘结果,溢出结果如您所愿(它返回 64 位结果的下半部分)。

但是,据我所知,实际上没有办法获得溢出(高 32 位),但是您在答案中显示的模数会消除该信息,所以我认为这不是您想要的。如果他们要溢出,他们无论如何都必须根据签名和未签名来区分它。

我知道这在 Chrome、Firefox 和 Opera 中有效,但不确定其余部分,但很确定 IE 没有它(典型)。您需要退回到诸如 this one 之类的 shim。

【讨论】:

  • 我认为您将 32 位/64 位与无符号/有符号混淆了。
  • 不,当你将两个 32 位数字乘以二进制补码时,它会产生 64 位结果,尽管无论乘法是否有符号,下半部分都是正确的——它是上半部分,溢出,因签名而异。见stackoverflow.com/questions/14063599/…
  • @TND,我正在编写一个类似于 hashCode 的函数,其中我被告知要实现的算法具有 32 位 int 并期望 Math.imul() 提供的行为。我建议您删除有关它无法获得高 32 位的部分以使答案更清晰。
  • 还有iadd吗?添加正确溢出?我的基于 Javascript 的 JVM 需要这个
【解决方案3】:

实现此目的的另一种方法是转换为可以在转换回整数之前删除多余字节的格式。 这对于 JS 来说可能不是最优的,但在操作符非常受限的环境中可能会有所帮助。

例如十六进制:

var hugeInteger = 999999999999999;
var ui32 = parseInt(hugeInteger.toString(16).slice(-8), 16);
// ui32 == 2764472319

也可以从hugeInteger.toString(16).slice(0,-8)获取溢出

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-09-12
    • 1970-01-01
    • 2023-01-03
    • 1970-01-01
    • 1970-01-01
    • 2016-01-22
    • 2014-02-09
    • 2017-09-17
    相关资源
    最近更新 更多