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

本文关键字:结果 字符串 BigInteger 十六进制 Java | 更新日期: 2023-09-27 18:11:14

问题:

这个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");

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

在将Java代码转换为C#时,我还遇到了以下问题:
Java

BigInteger k0 = new BigInteger(byte[]);

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

C#等价物:

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

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

以下是MSDN对BigInteger.Parse:的介绍

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

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

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

MSDN表示:

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

Java文档说:

返回一个字节数组,该数组包含此BigInteger的二进制补码表示形式。字节数组将按big-endian字节顺序排列:最高有效字节在第零个元素中。