2013-11-21 64 views
4

Tom Wu的优秀大整数库JSBN缺少longValue函数,因此我必须编写这样的自己。以下是我的代码,但它不能产生正确的结果。使用Javascript将BigInteger转换为Int64

 
var Cast_Int64 = function (v) 
{ 
    var bytes = v.toByteArray(); 
    var value = 
    (
    (new BigInteger(bytes[0]).and(new BigInteger(255))).shiftLeft(new BigInteger(56)) 
) 
    .or(
     (new BigInteger(bytes[1]).and(new BigInteger(255))).shiftLeft(new BigInteger(48)) 
) 
    .or(
     (new BigInteger(bytes[2]).and(new BigInteger(255))).shiftLeft(new BigInteger(40)) 
) 
    .or(
     (new BigInteger(bytes[3]).and(new BigInteger(255))).shiftLeft(new BigInteger(32)) 
) 
    .or(
     (new BigInteger(bytes[4]).and(new BigInteger(255))).shiftLeft(new BigInteger(24)) 
) 
    .or(
     (new BigInteger(bytes[5]).and(new BigInteger(255))).shiftLeft(new BigInteger(16)) 
) 
    .or(
     (new BigInteger(bytes[6]).and(new BigInteger(255))).shiftLeft(new BigInteger(8)) 
) 
    .or(new BigInteger(bytes[7]).and(new BigInteger(255))); 
    return value; 
}; 

我有一个整数字符串数组,我尝试转换为Int64,但它没有提供正确的答案。

整数字符串数组是:

 
var arr = [ 
"90655", 
"123423", 
"1", 
"9223372032559808512", 
"18446744071562067967", 
"4294967295", 
"18446744071562067968", 
"0", 
"346457745533644", 
"18446744073623153357" 
]; 

的正确答案(在使用(Int64) C#测试基)为:

 
90655 
123423 
1 
9223372032559808512 
-2147483649 
4294967295 
-2147483648 
0 
346457745533644 
-86398259 

而我的不正确的答案是:

 
99676226616033280 
135705023634997248 
72057594037927936 
9223372032559808512 
72057594029539327 
72057594021150720 
72057594029539328 
0 
88693182856612864 
72057594037590442 

我有jsbin,您可以在其中测试该功能。

编辑:如果我用这个代替Cast_Int64:

 
var Cast_Int64 = function (v) 
{ 
    return v; 
} 

然后一切顺利的话,但所有的数字应该是负的(在C#中试基地),将是错误的:

 
90655 
123423 
1 
9223372032559808512 
18446744071562067967 
4294967295 
18446744071562067968 
0 
346457745533644 
18446744073623153357 

该工程

代码(改编自接受的答案):

 
var Cast_Int64 = function (v) 
{ 
    if (v.compareTo(new BigInteger(2).pow(new BigInteger(63))) > 0) 
    v = v.subtract(new BigInteger(2).pow(new BigInteger(64))); 
    return v; 
} 

或更短(和更快一点):

 
var Cast_Int64 = function (v) 
{ 
    if (v.compareTo(new BigInteger("9223372036854775808",10)) > 0) 
    v = v.subtract(new BigInteger("18446744073709551616",10)); 
    return v; 
} 

我把替换代码jsbin。顺便说一句,已经有Cast_UInt64,Cast_Int32和Cast_UInt32函数。

回答

2

整数算术可以被认为是modular arithmetic(模,其中p是比特数)。所以负值可以表示为超过2^(p-1)的值,即-x = 2^p - x。例如,考虑x=1-1 = 2^p - 1。你可以在双方都加1,然后以2^p为模,你就会在两边都得到0

所以为了得到正确的结果,只是减去2^64(在你的情况p=64),从每一个值大于2^63

18446744073623153357 - 2^64 = -86398259 
18446744071562067968 - 2^64 = -2147483648 

BTW:这个,你可以推断出符号和无符号整数之间的连接。

+0

我该如何修改Cast_Int64函数? –

+0

算法在第二段粗略描述。你不明白什么部分?我不能告诉你要写什么代码,因为我没有看过你提到的库。 –

+0

我明白了。我会将替换添加到问题中。谢谢! –