这个6字节(48位)的数字是什么类型的…浮点数?整数



我必须读取MS-DOS程序使用的一些遗留数据文件。大部分都很简单,但我不能找出一种数据类型;一个表示整数的6字节序列。

一些例子:

+-----+-------------------+
| num | bytes as hex      |
+-----+-------------------+
|   0 | 00 00 00 00 00 00 |
|   1 | 80 7b 14 ae 47 61 |
|   2 | 80 20 d0 91 7b 14 |
|   3 | 80 20 d0 92 5c d0 |
|   4 | 80 20 d0 92 7b 14 |
|   5 | 80 20 d0 93 5c d0 |
|   6 | 80 20 d0 93 d0 bb |
|   7 | 80 20 d0 93 7a 14 |
|   8 | 80 20 d0 93 09 e2 |
|   9 | 80 20 d0 94 d1 9b |
|  10 | 80 20 d0 94 14 d0 |
|  16 | 84 48 e1 7a 14 7e |
|  20 | 85 0a d7 a3 70 1d |
|  32 | 86 ec 51 b8 1e 20 |
|  48 | 86 86 eb 51 b8 40 |
|  73 | 87 00 00 00 00 12 |
| 100 | 87 00 00 00 00 48 |
| 130 | 88 00 00 00 80 01 |
+-----+-------------------+
有人知道这是什么类型的格式吗?

可能有用的事情:

  • 文件格式来自MS-DOS时代(准确地说是1994年);
  • 文件格式在其他地方不使用特殊类型;
  • 将第一个字节的值增加一个通常会使数值加倍;
  • (其他)字节和整数通常是有符号的。

非常欢迎任何帮助!

快速更新

上面的例子显示了一个字节序列,在这里表示为十六进制值,从文件中剪切并粘贴到这里。我确信字节序列意味着表示一个数字,因为我可以在MS-DOS程序中更改数值,保存到文件中,并比较结果。


阅读,写入数据

为了读写48位实二进制格式,你可以看一下:
PHP: Convert double to Pascal 6-byte(48位)实格式

这看起来像是6字节[48位]真正的浮点pascal格式

帕斯卡雷亚尔的值在2.9 e -39 (2.9 x 10^-39)到1.7 e38 (1.7 x 10^38)之间。

如果是这种情况,您可以使用此方法将十六进制数转换为双精度数。

c#代码

[我从维基下面列出的文章结尾,但无论如何:Turbo Pascal Real]

// This program expects a byte array named real48[6] to be loaded with the 6 bytes of the real from the file. 
Double exponentbase = 129d;
Double exponent = real48[0] - exponentbase; // The exponent is offset so deduct the base.
// Now Calculate the mantissa
Double mantissa = 0.0;
Double value = 1.0;
// For Each Byte.
for (int i = 5; i >= 1; i--)
{
    int startbit = 7;
    if (i == 5)
    { startbit = 6; } //skip the sign bit.
    //For Each Bit
    for (int j = startbit; j >= 0; j--)
    {
        value = value / 2;// Each bit is worth half the next bit but we're going backwards.
        if (((real48[i] >> j) & 1) == 1) //if this bit is set.
        {
            mantissa += value; // add the value.
        }
    }
}
if (mantissa == 1.0 && real48[0] == 0) // Test for null value
    return 0.0;
if ((real48[5] & 0x80) == 1) // Sign bit check
    mantissa = -mantissa;
return (1 + mantissa) * Math.Pow(2.0, exponent);

如果您想要一个更现代的| POO代码来实现这一点,您可以使用Simeon Pilgrim在本文中向我们展示的代码:

Pascal 6字节实转IEEE 8字节双精度

警告要使用Pilgrim暴露的方法,您需要小心字节排序

// expl: 100=>                       87 00  00 00   00 48
var theMethodParam = new ushort[] { 0x0087, 0x0000, 0x4800 };

您可以在这里获得有关此主题的更多信息:

Turbo Pascal Real

这里有一个REAL48格式的描述:

http://docwiki.appmethod.com/appmethod/1.13/topics/en/Internal_Data_Formats The_Real48_type

来自JuanK的c#代码有多个错误:

Real48[0] == 0 

总是等价于值0.0

条件

if ((real48[5] & 0x80) == 1)

永远不会为真。这可以重写为

if ((real48[5] & 0x80) == 0x80)

或更简单的

if ((real48[5] & 0x80) != 0)

该符号必须在尾数加1后应用,即

mantissa = 1 + mantissa ;
if ( (real48[5] & 0x80) != 0 ) // Sign bit check
  mantissa = -mantissa;

这是我修改后的版本

// This program expects a byte array named real48[6] to be loaded with the 6 bytes of the real from the file.
// real48[0] == 0 is represents the value 0.
if ( real48[0] == 0 )
  return 0.0 ;
Double exponentbase = 129d;
Double exponent = real48[0] - exponentbase; // The exponent is offset so deduct the base.
// Now Calculate the mantissa
Double mantissa = 0.0;
Double value = 1.0;
// For Each Byte.
for (int i = 5; i >= 1; i--)
{
  int startbit = 7;
  if (i == 5)
  { startbit = 6; } //skip the sign bit.
  //For Each Bit
  for (int j = startbit; j >= 0; j--)
  {
    value = value / 2;// Each bit is worth half the next bit but we're going backwards.
    if (((real48[i] >> j) & 1) == 1) //if this bit is set.
    {
      mantissa += value; // add the value.
    }
  }
}
// The significand ia 1 + mantissa.
// This must come before applying the sign.
mantissa = 1 + mantissa ;
if ( (real48[5] & 0x80) != 0 ) // Sign bit check
  mantissa = -mantissa;
return (mantissa) * Math.Pow(2.0, exponent);

相关内容

最新更新