преобразование BigDecimal Java в c # -подобный десятичный - PullRequest
1 голос
/ 13 февраля 2012

В Java класс BigDecimal содержит значения в виде A * pow (10, B), где A - это дополнение к 2, нефиксированная длина бита, а B - 32-битное целое число.

В C # Десятичное число содержит значения в виде pow (-1, s) × c × pow (10, -e), где знак s равен 0 или 1, коэффициент c задается как 0 ≤ c

И я хочу преобразовать Java BigDecimal в нечто вроде c # Decimal в JAVA.Можете ли вы помочь мне.

У меня есть кое-что подобное

class CS_likeDecimal
{

    private int hi;// for 32bit most sinificant bit of c 
    private int mid;// for 32bit in the middle  
    private int lo;// for 32 bit the last sinificant bit

    .....
    public CS_likeDecimal(BigDecimal data)
    {
                ....

    }

}

На самом деле я нашел это Каков наилучший способ представления System.Decimal в буферах протокола? .

это буфер протокола для отправки десятичного числа c #, но в проекте protobuff-net это используется для отправки сообщения между c # (но я хочу между c # и JAVA)

message Decimal {
  optional uint64 lo = 1; // the first 64 bits of the underlying value
  optional uint32 hi = 2; // the last 32 bis of the underlying value
  optional sint32 signScale = 3; // the number of decimal digits, and the sign

}

Спасибо,

Ответы [ 2 ]

2 голосов
/ 13 февраля 2012

Decimal, который я использую в protobuf-net, в первую очередь предназначен для поддержки вероятного использования protobuf-net, используемого на обоих концах канала, который поддерживает фиксированный диапазон. Похоже, что диапазон обсуждаемых двух типов не одинаков, поэтому: они не являются надежно совместимыми.

Я бы предложил явно использовать альтернативное представление. Я не знаю, какие представления доступны для Java BigDecimal - есть ли прагматическая byte[] версия или string версия.

Если вы уверены, что масштаб и диапазон не будут проблемой, тогда должно быть в состоянии перетаскивать между двумя раскладками некоторую путаницу.

0 голосов
/ 22 февраля 2012

Мне нужно было написать конвертер BigDecimal в / из .Net Decimal.Используя эту ссылку: http://msdn.microsoft.com/en-us/library/system.decimal.getbits.aspx Я написал этот код, который может работать:

public static byte[] BigDecimalToNetDecimal(BigDecimal paramBigDecimal) throws IllegalArgumentException
{
    // .Net Decimal target
    byte[] result = new byte[16];

    // Unscaled absolute value
    BigInteger unscaledInt = paramBigDecimal.abs().unscaledValue();
    int bitLength = unscaledInt.bitLength();
    if (bitLength > 96)
        throw new IllegalArgumentException("BigDecimal too big for .Net Decimal");

    // Byte array
    byte[] unscaledBytes = unscaledInt.toByteArray();
    int unscaledFirst = 0;
    if (unscaledBytes[0] == 0)
        unscaledFirst = 1;

    // Scale
    int scale = paramBigDecimal.scale();
    if (scale > 28)
        throw new IllegalArgumentException("BigDecimal scale exceeds .Net Decimal limit of 28");
    result[1] = (byte)scale;

    // Copy unscaled value to bytes 8-15 
    for (int pSource = unscaledBytes.length - 1, pTarget = 15; (pSource >= unscaledFirst) && (pTarget >= 4); pSource--, pTarget--)
    {
        result[pTarget] = unscaledBytes[pSource];
    }

    // Signum at byte 0
    if (paramBigDecimal.signum() < 0)
        result[0] = -128;

    return result;
}

public static BigDecimal NetDecimalToBigDecimal(byte[] paramNetDecimal)
{
    int scale = paramNetDecimal[1];
    int signum = paramNetDecimal[0] >= 0 ? 1 : -1;
    byte[] magnitude = new byte[12];
    for (int ptr = 0; ptr < 12; ptr++) magnitude[ptr] = paramNetDecimal[ptr + 4];
    BigInteger unscaledInt = new BigInteger(signum, magnitude);

    return new BigDecimal(unscaledInt, scale);
}
...