将Delphi Extended转换为C# [英] Convert Delphi Extended to C#

查看:67
本文介绍了将Delphi Extended转换为C#的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何正确将Delphi Extended类型转换为C#十进制?

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

我已经尝试过这篇文章 https://stackoverflow.com/a/34550718/2550543 中的代码,认为它可以正常工作,但不能全部使用.

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

示例:

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

是的,如果两个值都不正确,则以3F字节结尾.

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

有人可以帮我吗?:)

我到目前为止使用的代码:

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

推荐答案

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

请注意您的优化.如果右侧参数为正,则向左移动为2的快速幂.对于负数,这将无法正常工作,因为幂运算的结果必须是负指数的浮点数,而移位只会产生整数结果.您可以通过删除此优化"来恢复正确答案:

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

我还纠正了您问题中链接答案中的代码.还要注意该答案的注意事项-此实现不能正确处理非正规数,NaN,INF和其他特殊情况.它也可能(应该)捕获扩展的 值的情况,这些情况是正常的,但超出了 double 的可表示范围.由您决定这对您的用例是否重要.

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.

这篇关于将Delphi Extended转换为C#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆