如何正确将Delphi Extended类型转换为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);
答案 0 :(得分:5)
return sign * (1 << (exp - 16383)) * (integral + mantissa);
请注意您的优化。如果右侧参数为正,则向左移动为2的快速幂。对于负数,这将无法正常工作,因为幂运算的结果必须是负数指数的浮点数,而移位只会产生整数结果。您可以通过删除此“优化”来恢复正确答案:
return sign * (Math.Pow(2, exp - 16383)) * (integral + mantissa);
我还纠正了您问题中链接答案中的代码。还要注意该答案的警告-此实现不能正确处理非正规数,NaN,INF和其他特殊情况。它也可以(应该)捕获extended
值的情况,这些值是正常的但在double
的可表示范围之外。由您决定这对您的用例是否重要。