关于DDIA中Thrift CompactProtocol int64变长编码的疑问
Thrift CompactProtocol int64 变长编码逻辑解析
首先明确Thrift CompactProtocol对有符号整数(如int64)的编码分为两步:ZigZag编码 + 变长字节编码。
1. ZigZag编码(处理有符号数)
目的是将负数映射为正奇数,正数映射为正偶数,让绝对值小的数(含负数)能用更少字节存储:
- 编码公式:
encoded = (value << 1) ^ (value >> 63)- 正数右移63位结果为0,所以正数编码后是
value * 2 - 负数右移63位结果为全1(补码特性),异或后等价于
-(value * 2 + 1)
- 正数右移63位结果为0,所以正数编码后是
- 解码公式:
value = (encoded >> 1) ^ -(encoded & 1)
2. 变长字节编码(处理无符号编码值)
将ZigZag后的无符号数拆分为7位一组,从最低位开始编码:
- 每次取当前数的最低7位作为字节的低7位
- 字节最高位设为
1表示后续还有更多字节,设为0表示这是最后一个字节 - 按「低位组在前,高位组在后」的顺序写入字节,直到原数右移7位后为0
针对1337的正确编码过程
1337是正数,ZigZag编码后为 1337 * 2 = 2674(二进制:101001110010)
对2674进行变长编码:
- 第一步:取最低7位
1110010(十进制114),2674右移7位得20(非0),所以第一个字节为1110010 | 0x80 = 0xF2(二进制11110010,最高位为1) - 第二步:处理20,取最低7位
0010100(十进制20),20右移7位得0,所以第二个字节为00010100(二进制00010100,最高位为0)
最终编码结果为两个字节:0xF2(11110010)和0x14(00010100),对应你看到的「1|1110010 0|0010100」(可能示例排版时少写了一个0)。
关于你提到的注释矛盾
你提到的「111011对应37、0010100对应13」明显不符合编码逻辑:
111011是十进制59,不是37;0010100是十进制20,不是13- 而你认为的
100101(37)和1101(13),组合后是37 + 13*128 = 1701,对应ZigZag解码后的原数是-851,和1337完全无关
这大概率是DDIA示例的排版或注释笔误,实际编码逻辑以上述步骤为准。
内容的提问来源于stack exchange,提问作者EugeneH
相关产品推荐
相关产品推荐

