我正在使用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
并且需要编码/解码价值第一)?首先,这不是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
s并将其写入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);
如果你想读取和写入这个特殊值,你需要做同样的事情,你将不得不读取和写入字节并将它们转换为你自己
这应该是游戏独有的内置价值。
它应该更像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
。
当然,这完全取决于游戏希望呈现的精确度。