首页 > 解决方案 > Javascript(GraalJS)与Java中的无符号右移>>>

问题描述

我有以下 Java 代码:

long num = 3482085570325547757;
// Discard all but the highest priority 31 bits
int result = (int) (num >>> 33); // Returns 405368112

我正在尝试在 Javascript 中做同样的事情(使用https://github.com/oracle/graaljs引擎),但是,它没有给我与 Java 代码相同的结果:

const num = 3482085570325547757;
// Discard all but the highest priority 31 bits
const result = num >>> 33; // Returns 1281508608

我认为这可能与 GraalJS 在内部将数字存储为整数和双精度数的方式有关?我也尝试使用下面的方法显式转换为 int ,但它也给了我与 Java 代码不同的结果:

const Long = Java.type('java.lang.Long');
const String = Java.type('java.lang.String');
const BigInteger = Java.type('java.math.BigInteger');
const num = 3482085570325547757;
// Discard all but the highest priority 31 bits
const result = BigInteger.valueOf(num >>> 33).intValue(); // Returns 1281508608

标签: javascriptjavabit-manipulationgraalvmgraaljs

解决方案


首先,您的 Java 示例无法编译。长文字需要一个L(或l)后缀:

long num = 3482085570325547757L;

然后,JavaScript 无法完全准确地存储该数字。

const num = 3482085570325547757;
console.log(num); // Displays 3482085570325547500

它可以存储的最大整数是 9007199254740991 ( Number.MAX_SAFE_INTEGER)。

BigInteger像你那样使用 Java 是行不通的,因为在创建BigInteger. 您需要使用字符串来正确创建BigInteger(或 JavaScript 的BitInt,或n后缀)。

然而,这也不是很有帮助,因为>>>对他们没有意义。引用 Java 的BigInteger文档

无符号右移运算符 (>>>) 被省略,因为此操作仅对固定大小的字有意义,而不适用于概念上具有无限数量的前导虚拟符号位的表示。

JavaScript 的BigInt.

但是,您可以使用正常的右移 ( >>) 运算符BigInt

const num = BigInt("3482085570325547757");
const bigIntResult = num >> BigInt(33); 
const result = Number(bigIntResult); // Convert to normal number

或者

const num = 3482085570325547757n;
const bigIntResult = num >> 33n; 
const result = Number(bigIntResult); // Convert to normal number

或者shiftRight()Java的方法BigInteger(未经测试,因为我没有GraalJS设置):

const BigInteger = Java.type('java.math.BigInteger');
const num = new BigInteger("3482085570325547757");
const result = num.shiftRight(33).intValue();

也可以看看:


推荐阅读