这个 6 字节(48 位)数字是什么类型……浮点数?整数?
What type is this 6 byte (48 bit) number... floating point? integer?
我必须阅读 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 位实数,您可以看一下:
这看起来像 6 字节[48 位] 真正的浮点 pascal 格式
帕斯卡实数的值介于 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);
如果你想要更现代的|您可以使用 Simeon Pilgrim 在本文中向我们展示的代码来实现 POO 代码:
Pascal 6-byte real to IEEE 8-byte double
Warning To use the method exposed by Pilgrim you need to be careful with byte ordering
// expl: 100=> 87 00 00 00 00 48
var theMethodParam = new ushort[] { 0x0087, 0x0000, 0x4800 };
您可以在此处获取有关此主题的更多信息:
这里有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);
我必须阅读 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 位实数,您可以看一下:
这看起来像 6 字节[48 位] 真正的浮点 pascal 格式
帕斯卡实数的值介于 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);
如果你想要更现代的|您可以使用 Simeon Pilgrim 在本文中向我们展示的代码来实现 POO 代码:
Pascal 6-byte real to IEEE 8-byte double
Warning To use the method exposed by Pilgrim you need to be careful with byte ordering
// expl: 100=> 87 00 00 00 00 48 var theMethodParam = new ushort[] { 0x0087, 0x0000, 0x4800 };
您可以在此处获取有关此主题的更多信息:
这里有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);