有什么最佳的启发式方法可以用来识别一块 X 4 字节的数据是整数还是浮点数? 人类可以很容易地做到这一点,但我希望以编程方式实现。
我意识到,由于每种位的组合都会产生一个有效的整数,并且(几乎?)所有位组合也会产生一个有效的浮点数,因此无法确定。但我仍然想确定最可能的候选者(实际上总是正确的;或者至少,人类可以做到)。
例如,让我们取一系列 4 字节的原始数据,并首先将其打印为整数,然后打印为浮点数:
1 1.4013e-4510 1.4013e-4444 6.16571e-445000 7.00649e-421024 1.43493e-420 00 0-5 -nan11 1.54143e-44
很明显,它们是整数。
现在,另一个例子:
1065353216 11084227584 51085276160 5.51068149391 1.333331083179008 4.51120403456 1000 0-1110651699 -0.11195593728 50000
这些显然是浮点数。
PS:我正在使用 C++,但你可以用任何语言、伪代码或只是用英语回答。
回答:
你要查看的是高 8 或 9 位。那是浮点值的符号和尾数所在的位置。这里的 0x00 0x80 和 0xFF 对于有效的浮点数据来说非常罕见。
特别是如果高 9 位全部为 0,那么只有当所有 32 位都为 0 时,这才是有效的浮点值。另一种说法是,如果指数为 0,则尾数也应为零。如果高位为 1 并且接下来的 8 位为 0,这是合法的,但也不太可能是有效的。它表示 -0.0,这是一个合法的浮点值,但没有意义。
用数字表示。如果高字节是 0x00(或 0x80),那么该值的大小最多为 2.35e-38。普朗克常数为 6.62e-34 m2kg/s,大了 4 个数量级。质子的估计直径远大于此(估计为 1.6e−15 米)。音频数据的最小非零值约为 2.3e-10。你不太可能看到浮点值是任何真实的合法测量值,并且小于 2.35e-38 但不是零。
反过来,如果高字节是 0xFF,那么该值要么是无限大,要么是 NaN,要么大于 3.4e+38。宇宙的年龄估计为 1.3e+10 年(1.3e+25 飞秒)。可观测宇宙大约有 e+23 颗恒星,阿伏伽德罗常数为 6.02e+23。同样,大于 e+38 的浮点值很少出现在合法测量中。
这并不是说 FPU 无法加载或生成此类值,如果你使用现代 FPU,你肯定会在计算的中间值中看到它们。现代 FPU 将加载一个指数为 0 但其他位不为 0 的浮点值。这些被称为非规格化值。这就是为什么你看到小的正整数显示为 e-42 范围内的浮点值,即使浮点的正常范围仅下降到 e-38。
全为 1 的指数表示无穷大。你可能不会在你的数据中找到无穷大,但你比我更清楚。 -Infinity 是 0xFF800000,+Infinity 是 0x7F800000,Infinity 的尾数中除 0 之外的任何值都是错误的。错误的无穷大用作 NaN。
将 NaN 加载到浮点寄存器中可能会导致它抛出异常,因此在相当确定你的数据是 int 之前,你希望使用整数数学来猜测你的数据是浮点数还是整数。