我的工作是将多个数字分配给一个长整数。 1. 17位数字 2. 7位数字 3. 17位数字 4. 7位数字 5. 13位数字 6. 3位数字
一个函数将这6个整数打包成一个long 第二个功能从一开始读取这6个整数并打印信息
当我编译它时,我得到了错误的数字。 ( 像这样 ) 来电者:2012年 来电区:92 被叫者:16398 Callee_zone:123 持续时间:0 关税: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);
//---Printing---
System.out.println("Caller: " + caller);
System.out.println("Caller_zone: " + caller_zone);
System.out.println("Callee: " + callee);
System.out.println("Callee_zone: " + callee_zone);
System.out.println("Duration: " + duration);
System.out.println("Tariff: " + tariff);
//-----------------------------------------------
}
}`
答案 0 :(得分:2)
编码器为每个项目分配错误的位数。例如:
//---1st---
example = caller;
res = res | example;
res = res << 17;
好吧,让我们首先简化一下:
//---1st---
res = res | caller;
res = res << 17;
由于移位是最后一步,因此它为 next 项目分配了17位。但是caller
的大小是17,而不是下一个项目caller_zone的大小。因此大小不正确,事情变得混乱起来。
它应该看起来像这样,在新的位上写上“ before”:
//---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;
此外,解码器错过了移位。出于明显的原因,移位模式应该是编码器的“镜像”,因此检查它是否“对齐”非常容易。掩码比较难检查,尤其是十进制会掩盖真实值。
答案 1 :(得分:1)
通过执行以下操作可以大大缩短您的代码:
public static int compareTimeOfDates(Date date1, Date date2) {
return convertToLocalTimeViaInstant(date1).compareTo(convertToLocalTimeViaInstant(date2));
}
测试
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
AND运算符,其文字为&
,将long
的值隐式扩展为{{1} } 之前 int
左移值。在long
方法中进行位屏蔽的另一个好处是,太大的输入会被“截断”到支持的位数,从而防止溢出。
此外,可以将<<
有符号扩展的移位运算符更改为encode
无符号移位运算符,但这没有关系,因为在之后应用了位掩码移位,因此无论如何都将符号位丢弃。