Tom Wu's excellent big integer library JSBN is missing the longValue function, so I have to write such myself. Below is my code, but it cannot produce right results.
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;
};
I have an array of integer strings, which I try to cast to Int64, but it doesn't provide right answers.
The array of integer strings is:
var arr = [
"90655",
"123423",
"1",
"9223372032559808512",
"18446744071562067967",
"4294967295",
"18446744071562067968",
"0",
"346457745533644",
"18446744073623153357"
];
The right answers (in C# test base using (Int64)
) are:
90655
123423
1
9223372032559808512
-2147483649
4294967295
-2147483648
0
346457745533644
-86398259
And my incorrect answers are:
99676226616033280
135705023634997248
72057594037927936
9223372032559808512
72057594029539327
72057594021150720
72057594029539328
0
88693182856612864
72057594037590442
I have jsbin, where you can test the function.
EDIT: If I replace Cast_Int64 with this:
var Cast_Int64 = function (v)
{
return v;
}
then all goes well, but all numbers that should be negative (in C# test base), will be wrong:
90655
123423
1
9223372032559808512
18446744071562067967
4294967295
18446744071562067968
0
346457745533644
18446744073623153357
Code that works (adapted from the accepted answer):
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;
}
Or shorter (and a bit faster):
var Cast_Int64 = function (v)
{
if (v.compareTo(new BigInteger("9223372036854775808",10)) > 0)
v = v.subtract(new BigInteger("18446744073709551616",10));
return v;
}
I put the replaced code in jsbin. BTW, there are already Cast_UInt64, Cast_Int32 and Cast_UInt32 functions.