【问题标题】:Bitwise operations, wrong result in Dart2Js按位运算,Dart2Js 中的错误结果
【发布时间】:2013-06-29 23:04:45
【问题描述】:

我正在使用 Dart 对 32 位整数进行 ZigZag 编码。这是我正在使用的源代码:

int _encodeZigZag(int instance) => (instance << 1) ^ (instance >> 31);
int _decodeZigZag(int instance) => (instance >> 1) ^ (-(instance & 1));

代码在 DartVM 中按预期工作。

但在 dart2js 中,如果我输入负数,_decodeZigZag 函数将返回无效结果。例如-10-10 被编码为19,应该解码回-10,但它被解码为4294967286。如果我在 Chrome 的 JavaScript 控制台中运行 (instance &gt;&gt; 1) ^ (-(instance &amp; 1)),我会得到 -10 的预期结果。这意味着对我来说,Javascript 应该能够使用它的数字模型正确运行此操作。

但 Dart2Js 生成以下 JavaScript,看起来与我在控制台中测试的代码不同:

return ($.JSNumber_methods.$shr(instance, 1) ^ -(instance & 1)) >>> 0;

为什么 Dart2Js 会在函数中添加一个使用过的右移 0?如果没有转变,结果会如预期的那样。

现在我想知道,这是 Dart2Js 编译器中的错误还是预期的结果?有没有办法强制 Dart2Js 输出正确的 javascript 代码?

还是我的 Dart 代码错了?

PS:也测试了将 XOR 拆分为其他操作,但 Dart2Js 仍在添加右移:

final a = -(instance & 1);
final b = (instance >> 1);

return (a & -b) | (-a & b);

结果:

a = -(instance & 1);
b = $.JSNumber_methods.$shr(instance, 1);
return (a & -b | -a & b) >>> 0;

【问题讨论】:

    标签: dart dart2js zigzag-encoding


    【解决方案1】:

    出于效率原因,dart2js 将 Dart 编号编译为 JS 编号。然而,JS 只提供一种数字类型:双精度数。此外,JS 中的位操作总是被截断为 32 位。

    在许多情况下(如密码学),处理无符号 32 位更容易,因此 dart2js 编译位操作,使其结果为无符号 32 位数字。

    这两种选择(有符号或无符号)都不是完美的。最初 dart2js 编译为带符号的 32 位,只有当我们过于频繁地绊倒它时才会更改。正如您的代码所示,这并不能消除问题,只是将其转移到不同的(希望不太频繁)用例。

    不兼容的数字语义一直是 dart2js 中的一个长期错误,但修复它需要时间并且可能会减慢生成的代码。在短期内,Dart 开发人员(编译为 JS)需要了解这个限制并解决它。

    【讨论】:

      【解决方案2】:

      看起来我找到了输出正确结果的等效代码。 dart vm 和 dart2js 的单元测试都通过了,我现在将使用它。

      int _decodeZigZag(int instance) => ((instance & 1) == 1 ? -(instance >> 1) - 1 : (instance >> 1));
      

      Dart2Js 这次没有添加班次。我仍然会对这种行为的原因感兴趣。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-08-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-06-01
        • 1970-01-01
        • 2021-02-13
        相关资源
        最近更新 更多