Stefan Steiger
Stefan Steiger

Reputation: 82186

Java vs. C#: BigInteger hex string yields different result?

Question:

This code in Java:

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

produces (in java) the number

179399505810976971998364784462504058921

However, when I use C#,

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

i don't get the same number, I get:

-160882861109961491465009822969264152535

However, when I create the number directly from decimal, it works

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

I tried converting the hex string in a byte array and reversing it, and creating a biginteger from the reversed array, just in case it's a byte array with different endianness, but that didn't help...

I also encountered the following problem when converting Java-Code to C#:
Java

BigInteger k0 = new BigInteger(byte[]);

to get the same number in C#, I must reverse the array because of different Endianness in the biginteger implementation

C# equivalent:

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

Upvotes: 2

Views: 836

Answers (1)

Lucas Trzesniewski
Lucas Trzesniewski

Reputation: 51330

Here's what MSDN says about BigInteger.Parse:

If value is a hexadecimal string, the Parse(String, NumberStyles) method interprets value as a negative number stored by using two's complement representation if its first two hexadecimal digits are greater than or equal to 0x80. In other words, the method interprets the highest-order bit of the first byte in value as the sign bit. To make sure that a hexadecimal string is correctly interpreted as a positive number, the first digit in value must have a value of zero. For example, the method interprets 0x80 as a negative value, but it interprets either 0x080 or 0x0080 as a positive value.

So, add a 0 in front of the parsed hexadecimal number to force an unsigned interpretation.

As for round-tripping a big integer represented by a byte array between Java and C#, I'd advise against that, unless you really have to. But both implementations happen to use a compatible two's complement representation, if you fix the endianness issue.

MSDN says:

The individual bytes in the array returned by this method appear in little-endian order. That is, the lower-order bytes of the value precede the higher-order bytes. The first byte of the array reflects the first eight bits of the BigInteger value, the second byte reflects the next eight bits, and so on.

Java docs say:

Returns a byte array containing the two's-complement representation of this BigInteger. The byte array will be in big-endian byte-order: the most significant byte is in the zeroth element.

Upvotes: 7

Related Questions