问题描述
我正在32位上进行 ZigZag 编码Dart的整数.这是我正在使用的源代码:
I'm doing ZigZag encoding on 32bit integers with Dart. This is the source code that I'm using:
int _encodeZigZag(int instance) => (instance << 1) ^ (instance >> 31);
int _decodeZigZag(int instance) => (instance >> 1) ^ (-(instance & 1));
代码在DartVM中按预期工作.
The code works as expected in the DartVM.
但是在dart2js中,如果我输入负数,则 _decodeZigZag
函数将返回无效结果.例如 -10
. -10
编码为 19
,应解码回 -10
,但解码为 4294967286
.如果我在Chrome的JavaScript控制台中运行(instance>> 1)^(-(instance& 1))
,我将得到 -10
的预期结果.对我来说,这意味着Javascript应该能够使用其数字模型正确运行此操作.
But in dart2js the _decodeZigZag
function is returning invalid results if I input negativ numbers. For example -10
. -10
is encoded to 19
and should be decoded back to -10
, but it is decoded to 4294967286
. If I run (instance >> 1) ^ (-(instance & 1))
in the JavaScript console of Chrome, I get the expected result of -10
. That means for me, that Javascript should be able to run this operation properly with it number model.
但是Dart2Js生成以下JavaScript,看起来与我在控制台中测试的代码不同:
But Dart2Js generate the following JavaScript, that looks different from the code I tested in the console:
return ($.JSNumber_methods.$shr(instance, 1) ^ -(instance & 1)) >>> 0;
为什么Dart2Js向该函数添加一个已使用的右移0?如果没有这种转变,结果将与预期的一样.
Why does Dart2Js adds a usinged right shift by 0 to the function? Without the shift, the result would be as expected.
现在我想知道,这是Dart2Js编译器中的错误还是预期的结果?有没有办法强迫Dart2Js输出正确的javascript代码?
Now I'm wondering, is it a bug in the Dart2Js compiler or the expected result? Is there a way to force Dart2Js to output the right javascript code?
还是我的Dart代码错误?
Or is my Dart code wrong?
PS :还进行了将XOR拆分为其他操作的测试,但是Dart2Js仍在添加右移:
PS: Also tested splitting up the XOR into other operations, but Dart2Js is still adding the right 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;
推荐答案
出于效率原因,dart2js将Dart数字编译为JS数字.但是,JS只提供一种数字类型:双精度.此外,JS中的位运算始终被截断为32位.
For efficiency reasons dart2js compiles Dart numbers to JS numbers. JS, however, only provides one number type: doubles. Furthermore bit-operations in JS are always truncated to 32 bits.
在许多情况下(例如密码学),更容易处理无符号的32位,因此dart2js会编译位操作,以便其结果为无符号的32位数字.
In many cases (like cryptography) it is easier to deal with unsigned 32 bits, so dart2js compiles bit-operations so that their result is an unsigned 32 bit number.
选择(带符号或无符号)都不是完美的选择.最初dart2js编译为带符号的32位,并且仅在我们过于频繁地对其进行修改时才进行了更改.如您的代码所示,这并不能解决问题,只是将其转移到不同的(希望是不那么频繁的)用例上.
Neither choice (signed or unsigned) is perfect. Initially dart2js compiled to signed 32 bits, and was only changed when we tripped over it too frequently. As your code demonstrate, this doesn't remove the problem, just shifts it to different (hopefully less frequent) use-cases.
不兼容的数字语义是dart2js中的一个长期存在的错误,但是解决它会花费时间并且有可能减慢生成的代码的速度.在短期内,Dart开发人员(编译为JS)需要了解此限制并加以解决.
Non-compliant number semantics have been a long-standing bug in dart2js, but fixing it will take time and potentially slow down the resulting code. In the short-term future Dart developers (compiling to JS) need to know about this restriction and work around it.
这篇关于按位运算,Dart2Js中的错误结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!