如何将数字编码到自定义范围内

How to encode a number into custom range

我需要为浮点值编写动态压缩。动态部分是,最终用户将提供边界和精度,其余部分必须处理。

第一部分是计算需要多少位。我使用的公式如下:

log2(bound x precision) + 1

举个例子

绑定:256 单位 | 精度:每单位 512

所以符号位需要 17 + 1,所以我总共需要 18 位。

我现在的问题是如何将数字转换成我的压缩格式?

例如号码 212.128456

肯定会丢失精度,这很好,但我无法理解将此值纳入范围所需的数学运算。

使用 18 位可以生成的最大数字是 (2^n) 所以 2^17 是 131072 所以当使用 18 位时我们的取值范围是 [-131072, 131071]。

因此,如果我将 212.128456 移动 1000,我将收到 212128.456。如果我只得到 abs 值,我有 212128。这比 131071 大。那么我怎样才能适应它?

适合这个数字的正确原因是什么?

简短回答:您将值移动了 1000,但移动本应仅移动 512。


更长的答案:让我们用你的例子 bound of 256--我假设这意味着数字被限制在区间 [-256, 255]。 精度为 512——我假设这意味着您希望绝对精度为 1/512,这本身意味着我们存储的数字最多为 1/512给定的数字。

如您所说,我们需要 18 位来执行此操作。我们如何存储数字 212.128456?

首先我们将这个数拆分为符号和绝对值,分别为+和212.128456。由于精度为 512,我们将该绝对值乘以 512 得到 108609.769472。我们现在将其四舍五入为最接近的整数并得到 108610。请注意 2**17 是 131072,因此我们的编码数字到目前为止适合 17 位。

为了得到符号位,让我们使用二进制补码算法,所以我们将符号值乘以 2**17。非负数的符号值为 0,而负数的符号值为 1。在我们的例子中,0 乘以 131072 为 0,我们将其添加到我们目前的编码数字中,得到我们的 最终值 108610。这适合 18 位。


为了解码该数字并查看我们实际存储的内容,我们向后执行此操作。我们知道我们的编码数字是 18 位的 108610。首先,我们通过将编码数字与 2**17 进行比较来获得符号,即 131072。我们的编码数字较小,因此解码数字的符号将是非负的,我们继续使用值 108610。如果我们的编码数字大于或等于 2**17 我们会说最终符号将是负数并从编码值中减去 2**17 以获得我们的下一个工作值。

由于我们的精度是 512,所以我们现在将数字 108610 除以 512 得到 212.12890625。最后,我们将之前找到的符号放在前面,得到 解码值 212.12890625.

这与原始值 212.128456 有多接近?减去这两个值得到 0.00045025。 (由于浮点不精确,我的 Python 实际上返回的值比那个值略大,但这不会改变这个讨论。)它小于 1/2200,所以我们很容易超过 1/512 的界限。


最后说明:由于在编码过程中我除以512然后四舍五入到最接近的整数,如果没有浮点数,这个过程中的精度实际上是1024计算的不精确性。这意味着您可以少用一位来存储编码值,您可以通过乘以 256 而不是 512 来实现这一点。但是,您不能确定在计算,所以如果 512 界限是一个困难的界限,你应该继续使用额外的位。