2011-03-22 61 views
2

我正在从Flash + ActionScript3中的网络中读取一个已签名的64位整数(Java long),并将其存储为两个uint(第一个和最后一个32位)。从两个任务中获取编号

var l:LongNumber = new LongNumber(); 
l.msb = socket.readUnsignedInt(); 
l.lsb = socket.readUnsignedInt(); 

我怎样才能将它转换成实际的数字为Number

我知道Number可以包含只有53位整数,而不是64,但它已经足够了(虽然能够抛出一个Error转换大数字时会很好)。

回答

1

是的,readDouble()在这里没用,它会将你的64位整数解释为一个IEEE 754格式的双精度浮点数(符号位+11指数位+52个小数位),这会让你一个垃圾结果。

(Number(msb)* Math.pow(2,32))+ Number(lsb)如果您需要支持负数,则不是完整的解决方案。如果您的数字为零或正数不大于2^63-1(因此符号位未设置),此代码只会得到正确的结果。如果符号位被设置,你的代码将有效地将64位解释为一个无符号整数,这不是Java发送给你的东西。如果你正在使用你的解决方案,并想知道为什么你总是得到积极的结果,这就是为什么。

在一行代码中支持负数和负数可能有一些非常酷的小技巧,但因为我现在无法解决这个问题,所以我会直接告诉你我看到的解决方案在我心中:

我会用msb & 0x80000000来读取符号位。如果没有设置,请使用上面的公式。如果已设置,请将您的数字从2的补码格式先转换为无符号格式:

msb =(msb^0xFFFFFFFF);

lsb =(lsb^0xFFFFFFFF)+ 1;

然后将您的forumla应用到msb和lsb,并且(因为符号位已设置)将结果数字乘以-1。

if (msb & 0x80000000) 
{ 
    msb ^= 0xFFFFFFFF; 
    lsb ^= 0xFFFFFFFF; 
    result = -(Number(msb)*4294967296 + Number(lsb) + 1); 
} 
else 
{ 
    result = Number(msb)*4294967296 + Number(lsb); 
} 
+0

我实际上并没有使用负数,尽管数字已经签名,但很好知道我是否曾经这么做过。 – 2011-03-24 16:21:51

+0

只是抬起头,我在我的计算过程中删除了符号位归零步骤,这是我思考过程的一部分,但不是实际计算的一部分 - 这是XORing的一部分自动发生的。如果你有一个负的int,你需要做的就是翻转所有的位并加一个得到2的补码,当你通过你的forumla时,它给你负数的绝对值,然后你乘以-1到获得实际价值。 – 2011-03-25 12:59:02

0

readDouble()
UPD:

var ba:ByteArray = new ByteArray(); 
ba.writeUnsignedInt(uint1); 
ba.writeUnsignedInt(uint2); 
ba.position = 0; 
result = ba.readDouble(); 
+0

如果我做'(msb << 32)+ lsb',它就会变成'msb + lsb'。 'readDouble'从浮点格式读取,而不是整数。 – 2011-03-22 17:40:22

+0

更新了我的回答 – www0z0k 2011-03-22 18:13:00

1

我发现我自己的解决方案(仅适用于正数)

(Number(msb) * Math.pow(2, 32)) + Number(lsb)

或硬编码2^32

(Number(msb) * 4294967296) + Number(lsb)