将数字转换为 16 位浮点数(存储为字节)并返回?

Convert a number into a 16-bit float (stored as bytes) and back?

出于(有损)压缩目的,我希望能够将 Javascript 数字转换为 16 位浮点表示形式以存储在 Uint16Arrays(或 Uint8Arrays,以最简单的为准)中。然后我会希望能够从 2 个字节转换回数字。我不需要对16位数字进行任何运算,它只是为了紧凑存储。

我找不到执行此操作的算法。它不需要是 IEEE 标准,只要精确到小数点后几位即可。

浮点数优于定点数,因为我不想预先确定值的范围。

编码

第一步是提取数字的指数和归一化分数。在 C 中,这是使用 JavaScript 中不可用的 frexp 函数完成的。谷歌搜索 frexp javascript 产生了几个实现。

例如,这里有一个 straight-forward implementation that extracts the bits directly from the IEEE representation using typed arrays. Here's a quick-and-dirty, inexact version using only Math functions. Here's an exact (?) version

第二步是使用位运算从获得的指数和尾数中创建您的 16 位 FP 数。请务必检查指数范围并四舍五入精度较低的尾数以获得更高的准确性。

解码

从您的 16 位 FP 数中提取指数和尾数。使用

将它们转换为 JavaScript 数字
// The value of 'adjust' depends on the size of the mantissa.
Math.pow(2, exponent - adjust) * mantissa

或者直接创建带有类型化数组的 IEEE 位模式。

次正规数,无穷大,NaN

次正规 JavaScript 数字可以简单地四舍五入为零。您必须决定是否要在 16 位格式中支持次正规数。这将使转换过程复杂化,以换取更准确的接近零的数字。

您还必须决定您的格式是否支持无穷大和 NaN。这些值的处理方式与 IEEE 格式类似。