java位移运算导致数值为负数
问题分析:
关键源代码:
int startTime = (int) (promotions >> 32);
int p = (int) (promotions & 0xFFFFFFFF);
int duraTime = p >> 16;
int rate = (int) (p & 0xFFFF);
int endTime = startTime + duraTime * 60;
源代码中:int duraTime = p >> 16;右移位后,符号位为1,导致了持续时间duraTime为负数的情况。
摘取代码,逐步分析验证:
Promotions= 5682372155986092840
int startTime = (int) (promotions >> 32);
int p = (int) (promotions & 0xFFFFFFFF); //p 的二进制为10001111 00011111 00100011 00101000(int一共32bit),被解析为负值
int duraTime = p >> 16; //p被认为是负数,右移位的时候,左边多出来的补1, duraTime的二进制为11111111 11111111 10001111 00011111(duraTime被解析
为负值)
int rate = (int) (p & 0xFFFF);
int endTime = startTime + duraTime * 60;
正确的代码:
int startTime = (int) (promotions >>> 32); // 无符号右移,防止出现负数
int p = (int) (promotions & 0xFFFFFFFF); //p 的二进制为10001111 00011111 00100011 00101000(int一共32bit)
int duraTime = p >>> 16; //右移位的时候,左边多出来的补0, duraTime的二进制为00000000 00000000 10001111 00011111(duraTime被解析为负
值)
int rate = (int) (p & 0xFFFF);
int endTime = startTime + duraTime * 60;
附带的java位运算相关的知识:
位移运算的过程:
移位运算符
包括:
“>> 右移,高位补符号位”;
“>>> 无符号右移,高位补0”;
“<< 左移”;
例子:
-5>>3=-1
1111 1111 1111 1111 1111 1111 1111 1011
1111 1111 1111 1111 1111 1111 1111 1111
因为是负数,高位补1
35 >> 2=8
0000 0000 0000 0000 0000 0000 0010 0011
0000 0000 0000 0000 0000 0000 0000 1000
因为是正数,高位补0
-5>>>3=536870911
1111 1111 1111 1111 1111 1111 1111 1011
0001 1111 1111 1111 1111 1111 1111 1111
因为是无符号位移,高位强制补0