【问题标题】:Convert Delphi Extended to C# [duplicate]将 Delphi Extended 转换为 C# [重复]
【发布时间】:2019-06-24 12:11:09
【问题描述】:

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

我已经尝试了这篇文章 https://stackoverflow.com/a/34550718/2550543 中的代码,其中一些值可以正常工作,但不是全部。

例子:

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

是的,两个不正确的值都以 3F 字节结尾,如果这意味着什么...

有人可以帮我吗? :)

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

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

【问题讨论】:

  • “十进制”到底是什么意思?因为在我看来,您的代码生成二进制浮点值而不是十进制值。

标签: c# delphi


【解决方案1】:
  return sign * (1 << (exp - 16383)) * (integral + mantissa);

注意你的优化。如果右侧参数为正,则左移作为 2 的快速幂。对于负数,这不会像您期望的那样起作用,因为幂运算的结果必须是负指数的浮点数,并且位移只会产生整数结果。您可以通过删除此“优化”来恢复正确答案:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-30
    • 2011-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多