结合lucene谈谈浮点数的压缩问题

先说说单精度float类型的压缩方法,lucene里面是将-1.0~125.0之间浮点数并且小数点部分为0的值使用1个字节压缩,当然必须排除-0.0f,其余的正数使用4个字节存储,负数使用5个字节存储(第一个字节是0xff)其余是原始的4个字节。

根据第一个字节就能对压缩的数值进行解析,-1~125的二进制形式为0b11111111~0b01111101,lucene将值加1并且将最高位置1,这样值就变成了0b10000000~0b11111110,考虑其余正数的最高位是符号位为0b00000000,其余负数的最高为是0b11111111,可以看出这三种情况是完全不冲突的,相信大家也能看出来为什么-1.0~125.0要排除-0.0f了吧,因为-0.0f的首字节是0b10000000跟前面(0b10000000~0b11111110)是冲突的。有兴趣的可以看看lucene的源码:

int intVal = (int) f;
    final int floatBits = Float.floatToIntBits(f);

    if (f == intVal
        && intVal >= -1
        && intVal <= 0x7D
        && floatBits != NEGATIVE_ZERO_FLOAT) {
      // small integer value [-1..125]: single byte
      out.writeByte((byte) (0x80 | (1 + intVal)));
    } else if ((floatBits >>> 31) == 0) {
      // other positive floats: 4 bytes
      out.writeInt(floatBits);
    } else {
      // other negative float: 5 bytes
      out.writeByte((byte) 0xFF);
      out.writeInt(floatBits);
    }

实际上双精度double类型的原理也是类似的,实现的时候跟float的方式稍有不同

猜你喜欢

转载自my.oschina.net/u/1268334/blog/2875194