我正在用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的(instance >> 1) ^ (-(instance & 1))控制台中运行JavaScript,就会得到-10的预期结果。这意味着,Javascript应该能够使用它的数字模型正确地运行这个操作。
但是Dart2Js生成以下JavaScript,这与我在控制台中测试的代码不同:
return ($.JSNumber_methods.$shr(instance, 1) ^ -(instance & 1)) >>> 0;为什么Dart2Js要在函数中添加一个使用的右移为0?如果没有这一转变,结果将如预期的那样。
现在我想知道,这是Dart2Js编译器中的错误还是预期的结果?有没有办法强迫Dart2Js输出正确的javascript代码?
还是我的Dart密码错了?
PS:也测试了将XOR拆分到其他操作中,但是Dart2Js仍然在添加正确的shift:
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;发布于 2013-07-02 19:24:12
出于效率原因,dart2js将Dart编号编译为JS数字。然而,JS只提供一个数字类型: doubles。此外,JS中的位操作总是被截断为32位。
在许多情况下(如密码学),处理无符号32位比较容易,因此dart2js编译位操作,以便它们的结果是一个无符号32位数。
选择(签名或未签名)都不是完美的。最初,dart2js编译为签名32位,并且只有当我们频繁地被它绊倒时才被更改。正如您的代码所演示的,这并不能消除问题,只是将其转移到不同的(希望不那么频繁)的用例中。
在dart2js中,不兼容的数字语义一直是一个长期存在的错误,但是修复它需要时间,并且可能会减慢产生的代码。在短期内,未来Dart开发人员(编译为JS)需要了解这一限制,并对其进行改进。
发布于 2013-07-02 18:50:10
看来我找到了输出正确结果的等价代码。dart vm和dart2js的单元测试通过,我现在将使用它。
int _decodeZigZag(int instance) => ((instance & 1) == 1 ? -(instance >> 1) - 1 : (instance >> 1));Dart2Js这次并没有增加一个转变。我还是会对这种行为的原因感兴趣。
https://stackoverflow.com/questions/17427976
复制相似问题