2 回答

TA贡献1816条经验 获得超4个赞
编码器为每个项目分配了错误的位数。例如:
//---1st---
example = caller;
res = res | example;
res = res << 17;
好吧,让我们首先简化一下:
//---1st---
res = res | caller;
res = res << 17;
由于移位是最后一步,因此它为下一项分配 17 位。但是 17 是 的大小caller,而不是下一项 caller_zone 的大小。所以尺寸是错误的,事情变得混乱。
它应该看起来更像这样,在新位中写入“之前”的移位:
//---1st---
res |= caller;
//---2nd---
res <<= 7;
res |= caller_zone;
//---3rd---
res <<= 17;
res |= callee;
//---4th---
res <<= 7;
res |= callee_zone;
//---5th---
res <<= 13;
res |= duration;
//---6th---
res <<= 3;
res |= tariff;
此外,解码器错过了一个转变。出于显而易见的原因,移位模式应该是编码器的“镜子”,因此很容易检查它是否“对齐”。掩码有点难以检查,尤其是在十进制中,它掩盖了真实值。

TA贡献1744条经验 获得超4个赞
通过这样做,您的代码可以大大缩短:
public static long encode(int caller, int caller_zone,
int callee, int callee_zone,
int duration, int tariff) {
return ((caller & 0x1FFFFL/*17 bits*/) << 47)
+ ((caller_zone & 0x0007FL/* 7 bits*/) << 40)
+ ((callee & 0x1FFFFL/*17 bits*/) << 23)
+ ((callee_zone & 0x0007FL/* 7 bits*/) << 16)
+ ((duration & 0x01FFFL/*13 bits*/) << 3)
+ (tariff & 0x00007L/* 3 bits*/);
}
public static int[] decode(long res) {
return new int[] {
(int) (res >> 47) & 0x1FFFF/*17 bits*/, // caller
(int) (res >> 40) & 0x0007F/* 7 bits*/, // caller_zone
(int) (res >> 23) & 0x1FFFF/*17 bits*/, // callee
(int) (res >> 16) & 0x0007F/* 7 bits*/, // callee_zone
(int) (res >> 3) & 0x01FFF/*13 bits*/, // duration
(int) res & 0x00007/* 3 bits*/ // tariff
};
}
测试
System.out.println(Arrays.toString(decode(encode(130999, 101, 7777, 99, 7000, 6))));
输出
[130999, 101, 7777, 99, 7000, 6]
在该encode方法中,这里应用的一个技巧是&带有long文字的AND 运算符,在左移int值long 之前 隐式地将值扩大到<<。在该encode方法中进行位屏蔽的额外好处是过大的输入被“截断”为支持的位数,从而防止溢出。
此外,有>>符号扩展移位运算符可以更改为>>>无符号移位运算符,但这无关紧要,因为位掩码是在移位后应用的,因此无论如何都会丢弃符号位。
添加回答
举报