我正在用C#处理二进制文件(旧视频游戏的3D模型文件)。该文件格式尚未正式记录,但其中一些已由游戏社区进行反向工程。
我在理解如何读取/写入4字节浮点值时遇到麻烦。社区成员向我提供了以下解释:
例如,字节
EE 62 ED FF
表示值-18.614。字节按小端顺序排列。前2个字节代表值的小数部分,后2个字节代表值的整个部分。
对于小数部分,
62 EE
转换为小数是25326。这表示1之内的分数,也可以描述为65536/65536。因此,将25326除以65536,您将得到0.386。对于整个部分,
FF ED
转换为十进制是65517。65517代表整数-19(即65517-65536)。这使值-19 + .386 = -18.614。
这种解释大体上是合理的,但我对两件事感到困惑:
BinaryWriter.Write(-18.613f)
将字节写为79 E9 94 C1
,所以我的假设是正在使用的二进制文件使用其专有的存储4字节浮点值的方法(即,我不能使用C#的float
可互换,是否需要先对值进行编码/解码)?答案 0 :(得分:1)
首先,这不是Floating Point Number,而是Fix Point Number
注意 :定点数具有为整数部分(左侧部分保留)的特定位数(或位数)小数点后的数字)
魔术数65536有什么意义
它的无符号16位数字可以容纳的最大值个数,或者2^16
,是有效的,因为您使用的数字是2 * 16位值,用于整数和小数部分。
所以我的假设是我正在使用的二进制文件使用自己的二进制文件 存储4字节浮点值的专有方法
再次没有错,。 Net 中的浮点值遵循IEEE Standard for Floating-Point Arithmetic (IEEE 754) technical standard
使用BinaryWriter.Write(float);
时,基本上只是将这些位移入byte
中,并将其写入Stream
。
uint TmpValue = *(uint *)&value;
_buffer[0] = (byte) TmpValue;
_buffer[1] = (byte) (TmpValue >> 8);
_buffer[2] = (byte) (TmpValue >> 16);
_buffer[3] = (byte) (TmpValue >> 24);
OutStream.Write(_buffer, 0, 4);
如果要读取和写入此特殊值,则需要做同样的事情,您将不得不读取和写入字节并将其转换为自己的字节
答案 1 :(得分:0)
这应该是游戏唯一的内置值。
应该更类似于Fraction Value
。
其中62 EE
代表值的Fraction Part
,FF ED
代表值的Whole Number Part
。
While Number Part
很容易理解,因此我不再赘述。
Fraction Part
的解释是:
每2个字节就有65536
个可能性(0〜65535)。
256 X 256 = 65536
因此,幻数65536
。
游戏本身必须具有内置算法,才能将前2个字节除以65536。
选择除此以外的任何数字将是waste of memory space
,结果为decreased accuracy of the value which can be represented
。
当然,这完全取决于游戏希望呈现的精度。