conversion BigDecimal Java to c#-like Decimal

北战南征 提交于 2020-01-05 09:14:07

问题


In Java BigDecimal class contains values as A*pow(10,B) where A is 2's complement which non-fix bit length and B is 32bit integer.

In C# Decimal contains values as pow (–1,s) × c × pow(10,-e) where the sign s is 0 or 1, the coefficient c is given by 0 ≤ c < pow(2,96) , and the scale e is such that 0 ≤ e ≤ 28 .

And i want to convert Java BigDecimal to Something like c# Decimal in JAVA. Can you help me .

I have some thing like this

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)
    {
                ....

    }

}

In fact I found this What's the best way to represent System.Decimal in Protocol Buffers?.

it a protocol buffer for send c# decimal ,but in the protobuff-net project use this to send message between c# (but i want between c# and 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

}

Thanks,


回答1:


the Decimal I use in protobuf-net is primarily intended to support the likely usage of protobuf-net being used at both ends of the pipe, which supports a fixed range. It sounds like the range of the two types in discussion is not the same, so: are not robustly compatible.

I would suggest explicitly using an alternative representation. I don't know what representations are available to Java's BigDecimal - whether there is a pragmatic byte[] version, or a string version.

If you are confident that the scale and range won't be a problem, then it should be possible to fudge between the two layouts with some bit-fiddling.




回答2:


I needed to write a BigDecimal to/from .Net Decimal converter. Using this reference: http://msdn.microsoft.com/en-us/library/system.decimal.getbits.aspx I wrote this code that could works:

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);
}


来源:https://stackoverflow.com/questions/9258313/conversion-bigdecimal-java-to-c-like-decimal

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!