Java BigDecimal , equivalent of C#'s Decimal(int[] bits) Constructor

I am trying to convert an input buffer (byte array) containing data that generated with a C# application to java data types. I have some issue with C#'s Decimal dataType.

C# example:

decimal decimalValue = 20.20M;
//converting a Decimal value to 4 integer vlaues
int[] intPieces= Decimal.GetBits(decimalValue); //{2020,0,0,131072}
//using native constructor to rebuild value
Decimal newDecimalValue = new decimal(intPieces); //20.20
Console.WriteLine("DecimalValue is " + newDecimalValue);

but there is no Decimal ( and also no Decimal(int[] bits) constructor ) in java.

C# Decimal Constructor (Int32[]) documention.

Jon Skeet
people
quotationmark

In Java, you'd use BigDecimal. That's not quite the same type, but it's reasonably close.

You just need to reconstruct the 96-bit integer as a BigInteger, then scale it and optionally negate it:

import java.math.BigDecimal;
import java.math.BigInteger;

public class Test {

    public static void main(String[] args) {
        int[] parts = { 2020, 0, 0, 131072 };
        BigInteger integer = BigInteger.valueOf(parts[2] & 0xffffffffL).shiftLeft(32)
            .add(BigInteger.valueOf(parts[1] & 0xffffffffL )).shiftLeft(32)
            .add(BigInteger.valueOf(parts[0] & 0xffffffffL));        
        BigDecimal decimal = new BigDecimal(integer, (parts[3] & 0xff0000) >> 16);
        if (parts[3] < 0) // Bit 31 set
        {
            decimal = decimal.negate();
        }
        System.out.println(decimal);
    }
}

Output:

20.20

The masking when constructing the BigInteger parts is there to effectively treat the values as unsigned - performing a bitwise AND with a long with the top 32 bits clear and the the bottom 32 bits set, we're constructing the same numeric value you'd get by casting each int to uint in C#.

people

See more on this question at Stackoverflow