【问题标题】:What type is this 6 byte (48 bit) number... floating point? integer?这个 6 字节(48 位)数字是什么类型...浮点数?整数?
【发布时间】:2015-11-02 21:24:58
【问题描述】:

我必须阅读一些 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 bits) real format

【问题讨论】:

  • 这个表是等价/查找表?所以int 1 等于80 7b 14 ae 47 61?
  • 不,它不是查找表,而是某种数据格式。
  • 文件中是这样的吗?我不确定我在看什么。这是文件的确切内容,还是您根据数据构建的?
  • @BurhanKhalid,问题已更新并澄清。

标签: binary hex


【解决方案1】:

这里有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);

【讨论】:

    【解决方案2】:

    这看起来像 6 字节[48 位] 真正的浮点帕斯卡格式

    帕斯卡实数的值介于 2.9E-39 (2.9 x 10^-39) 到 1.7E38 (1.7 x 10^38) 之间。

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

    C#代码

    [我从文章末尾列出的 wiki 中获取它,但无论如何: 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-byte real to IEEE 8-byte double

    警告要使用 Pilgrim 公开的方法,您需要注意字节顺序

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

    您可以在此处获取有关此主题的更多信息:

    Turbo Pascal Real

    【讨论】:

    • 您可能想为您的代码 sn-p 添加源/学分?
    • 当然!它已经有了!但无论如何我会让裁判很清楚;)......完成!
    • 我添加了一个关于“Simeon Pilgrim”文章代码的重要说明
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-29
    • 2011-05-29
    • 2018-12-18
    • 1970-01-01
    • 2020-09-30
    • 2015-03-12
    • 1970-01-01
    相关资源
    最近更新 更多