Compression “为什么我可以?”;“折叠”;在不丢失信息的情况下,将整数范围缩小到一半大小?

Compression “为什么我可以?”;“折叠”;在不丢失信息的情况下,将整数范围缩小到一半大小?,compression,computer-science,floating-point,math,Compression,Computer Science,Floating Point,Math,我试图理解并陷入一个特定的步骤,作者将一个有符号整数从某个范围映射到大小的一半范围,丢失了我认为需要的信息。我有一种感觉,作者正在使用一些标准的技巧,这对他们的观众来说是如此明显,以至于他们不费心解释,但对我来说是完全不透明的 被“折叠”的值是两个23位正整数(预测和实际浮点值的尾数)之间的差,介于1-223和223-1之间。作者将具有最高值(负值和正值)的数字“向内”移动,因此生成的范围是大小的一半,每个数字(0除外)从原始范围映射到两个可能的值。这让我想知道,这个过程应该如何颠倒来确定原始值

我试图理解并陷入一个特定的步骤,作者将一个有符号整数从某个范围映射到大小的一半范围,丢失了我认为需要的信息。我有一种感觉,作者正在使用一些标准的技巧,这对他们的观众来说是如此明显,以至于他们不费心解释,但对我来说是完全不透明的

被“折叠”的值是两个23位正整数(预测和实际浮点值的尾数)之间的差,介于1-223和223-1之间。作者将具有最高值(负值和正值)的数字“向内”移动,因此生成的范围是大小的一半,每个数字(0除外)从原始范围映射到两个可能的值。这让我想知道,这个过程应该如何颠倒来确定原始值。用作者自己的话来说:

我们计算最短模223的有符号校正器和指定该校正器所处的最紧间隔(1-2k,2k)的数字
k
。接下来,这个范围在0到22之间的数字
k
被压缩[…]。最后,对校正器的
k+1
有效位进行压缩

其伪代码如下所示:

void comp mantissa(int expo, int a, int p) {
  // c will be within [1-2^23 ... 2^23 -1]
  int c = a - p;
  // wrap c into [1-2^22 ... 2^22 ]
  if (c <= -(1<<22)) c += 1<<23;
  else if (c > (1<<22)) c -= 1<<23;
  // find tightest [1-2^k ... 2^k ] containing c
  int k = 0;
  // loop could be replaced with faster code
  int c1 = (c < 0 ? -c : c);
  while (c1) { c1 = c1 >> 1; k++ }
  // adjust k for case that c is exactly 2k
  if (k && (c == 1<<(k-1))) k--;

  // .. further code omitted for brevity
}
void comp尾数(int expo,int a,int p){
//c将在[1-2^23…2^23-1]范围内
int c=a-p;
//将c包装成[1-2^22…2^22]

如果(c当作者说他们正在考虑有效位“模2^23”时,这意味着数字将存储在23位整数中,因此相差2^23倍数的数字将“相同”,因为位模式是相同的。(参见)

由于c=a-p后的“换行”代码仅将2^23与c相加或相减,因此当您稍后通过计算a=c+p来反转此值时,您将得到正确的值,因为2^23无关紧要

这里有一个二进制的例子

a =             00000000000000000000001
p =             10000000000000000000100
c = a-p =      -10000000000000000000011

然后,因为cThanks太多了!这会让我花很长时间才注意到,我看起来完全错了。这是一个典型的例子,说明了当你真的陷入困境时,正确地提出问题是多么困难。感谢jcd找出了我的问题所在。也许这可以被编辑成更有用的东西,我会很感激的提示!
c = c+(1<<23) = 11111111111111111111101
a = c+p =      100000000000000000000001
a =             00000000000000000000001