我需要为浮点值编写动态压缩。动态部分是,最终用户将提供边界和精度,其余部分必须处理。
第一部分是弄清楚需要多少位。我使用的公式如下:
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大。那我怎么能适应呢?
这个号码适合的原因是什么?
答案 0 :(得分:2)
简短回答:您将价值转移了1000,但转移应该只有512。
更长的答案:让我们使用 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绑定是一个很难的,你应该继续使用额外的位。