将 JavaScript 代码移植到 Lua 时出现数字符号问题

Number sign issue when porting JavaScript code to Lua

我一直在尝试将一些 JavaScript 代码移植到 Lua。该代码对进出二进制流的数据进行编码和解码。

我在尝试移植一些可以包含有符号整数的 JavaScript 代码时遇到问题。 JavaScript 代码如下所示:

function encodeVarint(val) {
    const bigval = BigInt(val);
    console.log('r1: ' + (bigval >> 63n).toString());
    console.log('r2: ' + (bigval << 1n).toString());
}

encodeVarint(-332222);

此代码基于在此库中找到的代码:https://github.com/hathora/bin-serde-ts/blob/develop/index.ts

我在此处添加了这些函数的简化版本以进行测试:https://playcode.io/883024/

我的 Lua 代码是这样的(有一些日志记录以与 PlayCode 进行比较):

function encodeVarint(val)
    print("v", val)

    local r1 = bit.rshift(val, 63)
    local r2 = bit.lshift(val, 1)

    print("r1", r1)
    print("r2", r2)

    -- a work-around to get similar sign as in JavaScript
    local sign = val > 0 and 1 or -1

    local n = bit.bxor(r1, r2) * sign
    print("n", n)
    return tonumber(n)
end

function decodeVarint(val)
    local r1 = bit.rshift(val, 1)
    local r2 = -(bit.band(val, 1))
    return bit.bxor(r1, r2)
end

基于此处找到的代码:https://github.com/wolf81/bit-serde-lua/blob/main/bit-serde/bit-serde.lua

这里可以执行简化的例子:https://replit.com/@WolfgangSchreur/MysteriousEmbellishedSpools#main.lua

现在我看到的问题是,在 JavaScript 代码中,我得到以下 r1、r2 的值:

r1: -1
r2: -664444

而在 Lua 代码中,我得到以下内容:

r1:  1
r2:  -664444

所以我猜这使得 bit.bxor() 方法没有做它应该做的事情。由于符号在 Lua 版本中丢失。现在可以看到我手动添加了符号,但是当数据字节长度太多时这会导致问题(我想为符号添加了一个额外的位)

知道如何使 Lua 代码的行为与 JavaScript 代码相同吗?

JavaScript的右移运算符保留符号位:

The right shift operator (>>) shifts the first operand the specified number of bits to the right. Excess bits shifted off to the right are discarded. Copies of the leftmost bit are shifted in from the left. Since the new leftmost bit has the same value as the previous leftmost bit, the sign bit (the leftmost bit) does not change. Hence the name "sign-propagating".

MDN

Lua的位库有两个右移函数:

  1. bit.rshift填充0(正号位)和
  2. bit.arshift保留符号位。

Logical shifts treat the first argument as an unsigned number and shift in 0-bits. Arithmetic right-shift treats the most-significant bit as a sign bit and replicates it.

Lua Bit API Functions

bit.arshift 对最多 31 位的右移具有相同的行为。