为了账号安全,请及时绑定邮箱和手机立即绑定

Long 包含许多 int

Long 包含许多 int

慕桂英4014372 2021-12-10 14:48:33
我的练习是将多个数字分配给一个 long。1. 17 位数字 2. 7 位数字 3. 17 位数字 4. 7 位数字 5. 13 位数字 6. 3 位数字一个函数将这 6 个整数打包成一个 long 第二个函数从一个 long 中读取这 6 个整数并打印信息当我编译这个时,我得到了错误的数字。(像这样) Caller: 2012 Caller_zone: 92 Callee: 16398 Callee_zone: 123 Duration: 0 Tariff: 6`public class Problem_3_5{public static void main(String[] args){    info(encode(130999, 101, 7777, 99, 7000, 6));}public static long encode(int caller, int caller_zone,                          int callee, int callee_zone,                          int duration, int tariff) {    long res = 0;    long example = 0;    //---1st---    example = caller;    res = res | example;    res = res << 17;    //---2nd---    example = caller_zone;    res = res | example;    res = res << 7;    //---3rd---    example = callee;    res = res | example;    res = res << 17;    //---4th---    example = callee_zone;    res = res | example;    res = res << 7;    //---5th---    example = duration;    res = res | example;    res = res << 13;    //---6th---    example = tariff;    res = res | example;    //--END---    return res;    //---------------------------}public static void info(long res){    //---TARIFF----    long tariff = 0;        tariff = (res & 7);        res = res >>> 3;    //---DURATION---    long duration = 0;        duration = (res & 8191);        res = res >>> 13;    //---CALLEE_ZONE---    long callee_zone = 0;        callee_zone = (res & 127);        res = res >>> 7;    //---CALLEE---    long callee = 0;        callee = (res & 131071);        res = res >>> 17;    //---CALLER_ZONE---    long caller_zone = 0;        caller_zone = (res & 127);    //---CALLER---    long caller = 0;        caller = (res & 131071);
查看完整描述

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;

此外,解码器错过了一个转变。出于显而易见的原因,移位模式应该是编码器的“镜子”,因此很容易检查它是否“对齐”。掩码有点难以检查,尤其是在十进制中,它掩盖了真实值。


查看完整回答
反对 回复 2021-12-10
?
慕无忌1623718

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方法中进行位屏蔽的额外好处是过大的输入被“截断”为支持的位数,从而防止溢出。


此外,有>>符号扩展移位运算符可以更改为>>>无符号移位运算符,但这无关紧要,因为位掩码是在移位后应用的,因此无论如何都会丢弃符号位。


查看完整回答
反对 回复 2021-12-10
  • 2 回答
  • 0 关注
  • 103 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号