按位运算,Dart2Js中的错误结果

时间:2013-07-02 14:15:50

标签: dart dart2js zigzag-encoding

我正在使用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 >> 1) ^ (-(instance & 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;

2 个答案:

答案 0 :(得分:6)

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

在许多情况下(如加密),处理无符号32位更容易,因此dart2js编译位操作,因此它们的结果是无符号的32位数。

两种选择(有符号或无符号)都不是完美的。最初dart2js编译为有符号的32位,并且只有在我们经常跳过它时才会被更改。正如您的代码所示,这不会消除问题,只是将其转移到不同的(希望不那么频繁)用例。

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

答案 1 :(得分:3)

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

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

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