移位运算详解
下面是负-2的补码,也是负数的内存中实际存储的形式。
11111111111111111111111111111110
下面是-2的反码:
11111111111111111111111111111101
下面是正2的原码:
前面省略30个0:……10
##################
2的编码(原码)
00000000000000000000000000000010
2右移1位后的原码(相当于除2)
00000000000000000000000000000001
2的编码(原码)
00000000000000000000000000000010
2无符号右移1位后的原码(相当于除2)
00000000000000000000000000000001
################
负数有符号右移的步骤
-3的编码(补码):
11111111111111111111111111111101
-3右移1位后的补码(有符号,负数补1,正数补0)
11111111111111111111111111111110
-3的编码(补码):
11111111111111111111111111111101
-3无符号右移1位后的补码(无符号都补0)
01111111111111111111111111111110
########################
正数(-a)的编码(原码)
01111110000000110000000000000000
负数a的编码(补码)
10000001111111010000000000000000
负数a无符号右移(为正)后的编码(补码-并直接补0)
01000000111111101000000000000000
负数a的编码(补码)
10000001111111010000000000000000
负数a右移(仍然为负)的编码(补码)
11000000111111101000000000000000
负数a的编码(补)
10000001111111010000000000000000
负数a左移1位后(仍为负)的编码(补)
00000011111110100000000000000000
总结:
正数在内存中只有一种存在形式:原码。
负数在内存中也只有一种存在形式:补码。
只是人们发现,负数的编码可以由正数的编码(原)取反(反)再加1得到。
正数的编码可以由负数的编码(补)减1(反)再取反(原)得到
对于无符号右移,直接将正数(原)或负数(补)的编码从第一到第三十二依次右移,再在最最前端补0.
对于有符号右移:
正数:
正数(原)的编码从第一到第三十二依次右移,再在最最前端补0
负数:
负数(补)的编码从第一到第三十二依次右移,再在最最前端补1
左移都是在末尾补0。
java程序源代码:
package test03;
public class Test06_23 {
/**
* int a = 0x81fd0000; // 1000 0001 1111 1101 0000 0000 0000 0000 a >>>= 1;
* 变量a的值为:()。 (最高位为1)负数a,无符号右移后结果(直接补0)。 0100 0001 1111 1101 0000 0000 0000
* 0000 01000000111111101000000000000000
*
* 注意:负数在内在中永远是补码形式。只是人们发现,可以通过对正数的编码进行取反加1得到负数在内在中的形式。 也就是常说的负数以补码存在。
*
*
* @param args
*/
public static void main(String[] args) {
byte b1 = 1;
System.out.println(Integer.toBinaryString(b1));
byte b = (byte) ~b1;
System.out.println("下面是负-2的补码,也是负数的内存中实际存储的形式。");
System.out.println(Integer.toBinaryString(b));
System.out.println("下面是-2的反码:");
System.out.println(Integer.toBinaryString(b - 1));
System.out.println("下面是正2的原码:");
System.out.println("前面省略30个0:……" + Integer.toBinaryString(~(b - 1)));
System.out.println(b);
System.out.println();
System.out.println("##################");
System.out.println("2的编码(原码)");
System.out.println("000000000000000000000000000000"
+ Integer.toBinaryString(2));
System.out.println("2右移1位后的原码(相当于除2)");
System.out.println("0000000000000000000000000000000"
+ Integer.toBinaryString(2 >>> 1));
System.out.println();
System.out.println("2的编码(原码)");
System.out.println("000000000000000000000000000000"
+ Integer.toBinaryString(2));
System.out.println("2无符号右移1位后的原码(相当于除2)");
System.out.println("0000000000000000000000000000000"
+ Integer.toBinaryString(2 >>> 1));
System.out.println("################");
System.out.println("负数有符号右移的步骤");
System.out.println("-3的编码(补码):");
System.out.println(Integer.toBinaryString(-3));
System.out.println("-3右移1位后的补码(有符号,负数补1,正数补0)");
System.out.println(Integer.toBinaryString(-3 >> 1));
System.out.println();
System.out.println("-3的编码(补码):");
System.out.println(Integer.toBinaryString(-3));
System.out.println("-3无符号右移1位后的补码(无符号都补0)");
System.out.println("0" + Integer.toBinaryString(-3 >>> 1));
System.out.println();
System.out.println("########################");
int a = 0x81fd0000;
System.out.println("正数(-a)的编码(原码)");
System.out.println("0" + Integer.toBinaryString(-a));
System.out.println("负数a的编码(补码)");
System.out.println(Integer.toBinaryString(a));
System.out.println("负数a无符号右移(为正)后的编码(补码-并直接补0)");
System.out.println("0" + Integer.toBinaryString((a) >>> 1));
System.out.println();
System.out.println("负数a的编码(补码)");
System.out.println(Integer.toBinaryString(a));
System.out.println("负数a右移(仍然为负)的编码(补码)");
System.out.println(Integer.toBinaryString(a >> 1));
System.out.println();
System.out.println("负数a的编码(补)");
System.out.println(Integer.toBinaryString(a));
System.out.println("负数a左移1位后(仍为负)的编码(补)");
System.out.println("000000" + Integer.toBinaryString(a << 1));
}
}