先說說單精度float類型的壓縮方法,lucene裏面是將-1.0~125.0之間浮點數而且小數點部分爲0的值使用1個字節壓縮,固然必須排除-0.0f,其他的正數使用4個字節存儲,負數使用5個字節存儲(第一個字節是0xff)其他是原始的4個字節。源碼
根據第一個字節就能對壓縮的數值進行解析,-1~125的二進制形式爲0b11111111~0b01111101,lucene將值加1而且將最高位置1,這樣值就變成了0b10000000~0b11111110,考慮其他正數的最高位是符號位而且以0打頭0b0XXXXXXX,其他負數的最高位是0b11111111,能夠看出這三種狀況是徹底不衝突的,相信你們也能看出來爲何-1.0~125.0要排除-0.0f了吧,由於-0.0f的首字節是0b10000000跟前面(0b10000000~0b11111110)是衝突的。有興趣的能夠看看lucene的源碼:it
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的方式稍有不一樣float