Convert Delphi Extended to C# [duplicate]

只谈情不闲聊 提交于 2020-01-14 12:47:31

问题


How to correctly convert Delphi Extended type to C# decimal?

I have tried code from this post https://stackoverflow.com/a/34550718/2550543 ,with some values it works fine, but not with all.

Example :

000000000000A08C0B40 == 4500, correct
0050AA7D3A1E33D30140 == 6,59999, correct
00D0F753E3A59BC4F73F == 25769803,776, should be 0.006
00A0703D0AD7A3B0FD3F == 1481763717,12, should be 0.345

Yep, both incorrect values ends with 3F byte, if that means something ...

Can somebody help me with that? :)

Code i have used so far :

    var extendedSize = 10;
    var buf = new byte[extendedSize];

    // Populate buffer with something like: { 0x00, 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0xA2, 0x02, 0x40 } = 10.15
    // Read(buf, extendedSize);

    var sign = (buf[extendedSize - 1] & 0x80) == 0x80 ? -1 : 1;
    buf[extendedSize - 1] = (byte)(buf[extendedSize - 1] & 0x7F);
    var exp = BitConverter.ToUInt16(buf, extendedSize - 2);
    var integral = (buf[extendedSize - 3] & 0x80) == 0x80 ? 1 : 0;           

    // Calculate mantissa
    var mantissa = 0.0;
    var value = 1.0;
    var fractal = BitConverter.ToUInt64(buf, 0);

    while (fractal != 0)
    {
        value = value / 2;
        if ((fractal & 0x4000000000000000) == 0x4000000000000000) // Latest bit is sign, just skip it
        {
            mantissa += value;
        }
        fractal <<= 1;
    }

    return sign * (1 << (exp - 16383)) * (integral + mantissa);

回答1:


  return sign * (1 << (exp - 16383)) * (integral + mantissa);

Here be careful of your optimizations. Left shift works as a fast power of two if the right side argument is positive. For negative numbers this does not work as you would expect since the result of the power operation must be a floating point number for negative exponents and bit shifts will only produce an integer result. You can recover the correct answer by removing this "optimization" :

 return sign * (Math.Pow(2, exp - 16383)) * (integral + mantissa);

I've also corrected the code in the linked answer from your question. Do note the caveats from that answer as well - this implementation does not correctly handle denormal numbers, NaN, INF, and other special cases. It could (should) also catch cases of extended values which are normal but fall outside the representable range of double. It would be up to you to decide whether that is important for your use case.



来源:https://stackoverflow.com/questions/56736279/convert-delphi-extended-to-c-sharp

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