在 javascript 中对大数使用按位运算符
Using bitwise operators with large numbers in javascript
我正在编写此 Microsoft string decoding algorithm 的 Javascript 版本,但它在大量失败。这似乎是因为大小(整数/长)问题。如果我单步执行 C# 中的代码,我会看到 JS 实现在此行失败
n |= (b & 31) << k;
当值为(并且 C# 结果为 240518168576)时会发生这种情况
(39 & 31) << 35
如果我在 C# 中使用这些值,如果 b
是 int
,我可以复制 JS 问题。如果我将 b
设置为 long
它可以正常工作。
然后我检查了一个JS数字的最大大小,并将其与C# long result
进行了比较
240518168576 < Number.MAX_SAFE_INTEGER = true
所以..我可以看到发生了某种数字大小问题,但不知道如何强制 JS 将此数字视为长整数。
完整的 JS 代码:
private getPointsFromEncodedString(encodedLine: string): number[][] {
const EncodingString = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";
var points: number[][] = [];
if (!encodedLine) {
return points;
}
var index = 0;
var xsum = 0;
var ysum = 0;
while (index < encodedLine.length) {
var n = 0;
var k = 0;
debugger;
while (true) {
if (index >= encodedLine.length) {
return points;
}
var b = EncodingString.indexOf(encodedLine[index++]);
if (b == -1) {
return points;
}
n |= (b & 31) << k;
k += 5;
if (b < 32) {
break;
}
}
var diagonal = ((Math.sqrt(8 * n + 5) - 1) / 2);
n -= diagonal * (diagonal + 1) / 2;
var ny = n;
var nx = diagonal - ny;
nx = (nx >> 1) ^ -(nx & 1);
ny = (ny >> 1) ^ -(ny & 1);
xsum += nx;
ysum += ny;
points.push([ysum * 0.000001, xsum * 0.000001]);
}
console.log(points);
return points;
}
预期输入输出:
编码字符串
qkoo7v4q-lmB0471BiuuNmo30B
解码点数:
- 35.89431, -110.72522
- 35.89393, -110.72578
- 35.89374, -110.72606
- 35.89337, -110.72662
Bitwise operators treat their operands as a sequence of 32 bits
(zeroes and ones), rather than as decimal, hexadecimal, or octal
numbers. For example, the decimal number nine has a binary
representation of 1001. Bitwise operators perform their operations on
such binary representations, but they return standard JavaScript
numerical values.
(39 & 31) << 35
试图在只有 32
时移动 35 位
要解决此问题,您可以使用 BigInt
执行这些操作,然后将其向下转换回 Number
Number((39n & 31n) << 35n)
你可以试试这个:
function getPointsFromEncodedString(encodedLine) {
const EncodingString = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";
var points = [];
if (!encodedLine) {
return points;
}
var index = 0;
var xsum = 0;
var ysum = 0;
while (index < encodedLine.length) {
var n = 0n;
var k = 0n;
while (true) {
if (index >= encodedLine.length) {
return points;
}
var b = EncodingString.indexOf(encodedLine[index++]);
if (b === -1) {
return points;
}
n |= (b & 31n) << k;
k += 5n;
if (b < 32n) {
break;
}
}
var diagonal = ((Math.sqrt(8 * Number(n) + 5) - 1) / 2);
n -= diagonal * (diagonal + 1) / 2;
var ny = n;
var nx = diagonal - ny;
nx = (nx >> 1) ^ -(nx & 1);
ny = (ny >> 1) ^ -(ny & 1);
xsum += Number(nx);
ysum += Number(ny);
points.push([ysum * 0.000001, xsum * 0.000001]);
}
console.log(points);
return points;
}
我正在编写此 Microsoft string decoding algorithm 的 Javascript 版本,但它在大量失败。这似乎是因为大小(整数/长)问题。如果我单步执行 C# 中的代码,我会看到 JS 实现在此行失败
n |= (b & 31) << k;
当值为(并且 C# 结果为 240518168576)时会发生这种情况
(39 & 31) << 35
如果我在 C# 中使用这些值,如果 b
是 int
,我可以复制 JS 问题。如果我将 b
设置为 long
它可以正常工作。
然后我检查了一个JS数字的最大大小,并将其与C# long result
240518168576 < Number.MAX_SAFE_INTEGER = true
所以..我可以看到发生了某种数字大小问题,但不知道如何强制 JS 将此数字视为长整数。
完整的 JS 代码:
private getPointsFromEncodedString(encodedLine: string): number[][] {
const EncodingString = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";
var points: number[][] = [];
if (!encodedLine) {
return points;
}
var index = 0;
var xsum = 0;
var ysum = 0;
while (index < encodedLine.length) {
var n = 0;
var k = 0;
debugger;
while (true) {
if (index >= encodedLine.length) {
return points;
}
var b = EncodingString.indexOf(encodedLine[index++]);
if (b == -1) {
return points;
}
n |= (b & 31) << k;
k += 5;
if (b < 32) {
break;
}
}
var diagonal = ((Math.sqrt(8 * n + 5) - 1) / 2);
n -= diagonal * (diagonal + 1) / 2;
var ny = n;
var nx = diagonal - ny;
nx = (nx >> 1) ^ -(nx & 1);
ny = (ny >> 1) ^ -(ny & 1);
xsum += nx;
ysum += ny;
points.push([ysum * 0.000001, xsum * 0.000001]);
}
console.log(points);
return points;
}
预期输入输出:
编码字符串
qkoo7v4q-lmB0471BiuuNmo30B
解码点数:
- 35.89431, -110.72522
- 35.89393, -110.72578
- 35.89374, -110.72606
- 35.89337, -110.72662
Bitwise operators treat their operands as a sequence of 32 bits (zeroes and ones), rather than as decimal, hexadecimal, or octal numbers. For example, the decimal number nine has a binary representation of 1001. Bitwise operators perform their operations on such binary representations, but they return standard JavaScript numerical values.
(39 & 31) << 35
试图在只有 32
要解决此问题,您可以使用 BigInt
执行这些操作,然后将其向下转换回 Number
Number((39n & 31n) << 35n)
你可以试试这个:
function getPointsFromEncodedString(encodedLine) {
const EncodingString = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";
var points = [];
if (!encodedLine) {
return points;
}
var index = 0;
var xsum = 0;
var ysum = 0;
while (index < encodedLine.length) {
var n = 0n;
var k = 0n;
while (true) {
if (index >= encodedLine.length) {
return points;
}
var b = EncodingString.indexOf(encodedLine[index++]);
if (b === -1) {
return points;
}
n |= (b & 31n) << k;
k += 5n;
if (b < 32n) {
break;
}
}
var diagonal = ((Math.sqrt(8 * Number(n) + 5) - 1) / 2);
n -= diagonal * (diagonal + 1) / 2;
var ny = n;
var nx = diagonal - ny;
nx = (nx >> 1) ^ -(nx & 1);
ny = (ny >> 1) ^ -(ny & 1);
xsum += Number(nx);
ysum += Number(ny);
points.push([ysum * 0.000001, xsum * 0.000001]);
}
console.log(points);
return points;
}