在Javascript中将BigInteger转换为Int64

时间:2013-11-21 14:40:28

标签: javascript casting integer biginteger bigint

Tom Wu的优秀大整数库JSBN缺少longValue函数,所以我必须自己编写。下面是我的代码,但它无法产生正确的结果。

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函数。

1 个答案:

答案 0 :(得分:2)

整数算术可以被认为是modular arithmetic(模2^p,其中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:从中可以推断出有符号和无符号整数之间的连接。