Java与C#:BigInteger十六进制字符串产生不同的结果?

时间:2015-09-05 12:34:50

标签: java c# arrays biginteger endianness

问题:

Java中的代码:

BigInteger mod = new BigInteger("86f71688cdd2612ca117d1f54bdae029", 16);

生成(在java中)数字

179399505810976971998364784462504058921

但是,当我使用C#时,

BigInteger mod = BigInteger.Parse("86f71688cdd2612ca117d1f54bdae029", System.Globalization.NumberStyles.HexNumber); // base 16

我没有得到相同的号码,我得到:

-160882861109961491465009822969264152535

但是,当我直接从小数创建数字时,它可以正常工作

BigInteger mod = BigInteger.Parse("179399505810976971998364784462504058921");

我尝试在字节数组中转换十六进制字符串并将其反转,并从反转数组创建一个大整数,以防它是一个具有不同字节序的字节数组,但这并没有帮助..

将Java-Code转换为C#时,我也遇到了以下问题:
爪哇

BigInteger k0 = new BigInteger(byte[]);

要在C#中获得相同的数字,我必须反转数组,因为biginteger实现中的Endianness不同

C#等价物:

BigInteger k0 = new BigInteger(byte[].Reverse().ToArray());

1 个答案:

答案 0 :(得分:7)

以下是MSDN对BigInteger.Parse所说的内容:

  

如果value是十六进制字符串,Parse(String, NumberStyles)方法如果前两个十六进制数字大于或等于 0x80 <,则将值解释为使用二进制补码表示存储的负数。 / strong>即可。换句话说,该方法将值中第一个字节的最高位解释为符号位。要确保十六进制字符串被正确解释为正数,值中的第一个数字必须具有零值。例如,该方法将 0x80 解释为负值,但它将 0x080 0x0080 解释为正值。

因此,在解析的十六进制数字前添加0以强制执行无符号解释。

对于Java和C#之间由字节数组表示的大整数的往返,我建议不要这样做,除非你真的必须这样做。但是如果你修复了字节序问题,那么两个实现都会发生以使用兼容的二进制补码表示。

MSDN says

  

此方法返回的数组中的各个字节以 little-endian 顺序显示。也就是说,该值的低位字节在高位字节之前。数组的第一个字节反映了BigInteger值的前8位,第二个字节反映了接下来的8位,依此类推。

Java docs say

  

返回一个包含此BigInteger的两个补码表示的字节数组。字节数组将以 big-endian 字节顺序排列:最重要的字节位于第0个元素中。