Java中的位操作
2016-04-21 14:20
549 查看
1 机器码
要进行位操作,首先得了解数据以二进制保存的形式吧。这里我们只以定点数讲解,即原码、反码、补码的知识。浮点数的机器码比较复杂,一般不会考到浮点数的位操作。这里我只强调几点:
整数0的机器码是32位全为0;
32位全为1的整数是-1;
首位为0,其余31位为1的数就是 int 所能表示的最大正整数;
符号位为1,其余位全为0的不是 -0 ,而是int所能表示的最小负整数;
整数的机器码是以其补码形式表示的,所以整数的补码很直观,但是负数的可能就不那么直观了。
public static void main(String[] args) { for (int i = 0; i < 9; i++) { System.out.printf("i = %d\n 机器码:%-6s ;变负数:%-6s ; 取反:%-6s\n", i, Integer.toBinaryString(i), Integer.toBinaryString(-i), Integer.toBinaryString(~i)); } String MAX_VALUE = Integer.toBinaryString(Integer.MAX_VALUE); String MIN_VALUE = Integer.toBinaryString(Integer.MIN_VALUE); System.out.printf("\nInteger.MAX_VALUE: %d ; 机器码为:%s ; 长度:%d\n", Integer.MAX_VALUE, MAX_VALUE, MAX_VALUE.length()); System.out.printf("Integer.MIN_VALUE: %d ; 机器码为:%s ; 长度:%d\n", Integer.MIN_VALUE, MIN_VALUE, MIN_VALUE.length()); }
i = 0 机器码:0 ;变负数:0 ; 取反:11111111111111111111111111111111 i = 1 机器码:1 ;变负数:11111111111111111111111111111111 ; 取反:11111111111111111111111111111110 i = 2 机器码:10 ;变负数:11111111111111111111111111111110 ; 取反:11111111111111111111111111111101 i = 3 机器码:11 ;变负数:11111111111111111111111111111101 ; 取反:11111111111111111111111111111100 i = 4 机器码:100 ;变负数:11111111111111111111111111111100 ; 取反:11111111111111111111111111111011 i = 5 机器码:101 ;变负数:11111111111111111111111111111011 ; 取反:11111111111111111111111111111010 i = 6 机器码:110 ;变负数:11111111111111111111111111111010 ; 取反:11111111111111111111111111111001 i = 7 机器码:111 ;变负数:11111111111111111111111111111001 ; 取反:11111111111111111111111111111000 i = 8 机器码:1000 ;变负数:11111111111111111111111111111000 ; 取反:11111111111111111111111111110111 Integer.MAX_VALUE: 2147483647 ; 机器码为:1111111111111111111111111111111 ; 长度:31 Integer.MIN_VALUE: -2147483648 ; 机器码为:10000000000000000000000000000000 ; 长度:32
MAX_VALUE / MIN_VALUE
MAX_VALUE值为 2^31 -1 的常量,它表示 int 类型能够表示的最大值。
MIN_VALUE
值为 -2^31 的常量,它表示 int 类型能够表示的最小值。
为什么是31位而不是32位呢?因为最高位是符号位。第一位bit的基是2^0,第二位bit的基是2^2,……,第31位的基是2^30。所以MAX_VALUE的值为 2^31 -1,这个减一是经常容易被忽略的。那为什么10000000000000000000000000000000可以表示最小值呢? 因为这是一个巧妙的约定。
int t1 = Integer.MAX_VALUE; System.out.printf("Integer.MAX_VALUE is: %d; the bitString is: %s\n", t1, Integer.toBinaryString(t1)); t1++; System.out.printf("Integer.MAX_VALUE++ is: %d; the bitString is: %s\n", t1, Integer.toBinaryString(t1)); int t2 = Integer.MIN_VALUE; System.out.printf("Integer.MIN_VALUE is: %d; the bitString is: %s\n", t2, Integer.toBinaryString(t2)); t2--; System.out.printf("Integer.MIN_VALUE-- is: %d; the bitString is: %s\n", t2, Integer.toBinaryString(t2));
Integer.MAX_VALUE is: 2147483647; the bitString is: 1111111111111111111111111111111 Integer.MAX_VALUE++ is: -2 bbf6 147483648; the bitString is: 10000000000000000000000000000000 Integer.MIN_VALUE is: -2147483648; the bitString is: 10000000000000000000000000000000 Integer.MIN_VALUE-- is: 2147483647; the bitString is: 1111111111111111111111111111111
Java运算符的优先级
这里我们着重关注一下位移运算(左移<<、右移>>、无符号右移>>)的优先级,它们的优先级甚至低于加和减,但高于位运算。
java中>>与>>>的区别
有符号右移运算符>>
用来将一个数的各二进制位全部右移若干位。例如:a = a>>2,使a的各二进制位右移两位,移到右端的低位被舍弃,最高位则移入原来高位的值。如:a = 00110111,则a>>2=00001101
b=11010011,则b>>2 = 11110100
右移一位相当于除2 取商,而且用右移实现除法比除法运算速度要快。
无符号右移运算符>>>
用来将一个数的各二进制位无符号右移若干位,与运算符>>相同,移出的低位被舍弃,但不同的是最高位补0,如:a = 00110111,则a>>>2 = 00001101
b=11010011,则 b>>>2 = 00110100
位运算实例
题目:
m 为正整数。将 n 的二进制码中的 i–j 位的bit位换成 m的二进制码。
i是低位 j是高位。
i和j的设置一定与m和n的情况相符,不会出现异常。
代码
public static int updateBits(int n, int m, int i, int j) { System.out.printf("n: %s ; m: %s\n\n", Integer.toBinaryString(n), Integer.toBinaryString(m)); System.out.println("---------- Build mask ----------"); int full1 = ~0; // 全1 // 低位有 j+1 个0, 高位全为1 int left = full1 << j + 1; System.out.printf("The left of mask is: %s\n", Integer.toBinaryString(left)); // 高位全为0,低位有i个1 int right = full1 >>> (32 - i); System.out.printf("The right of mask is: %s\n", Integer.toBinaryString(right)); // Left和right进行按位或运算,就可以得到 i--j 位为0,其余位全为1的mask int mask = left | right; System.out.printf("The mask is: %s\n\n", Integer.toBinaryString(mask)); // 用 mask 将 n 上 i--j 位清零 int maskN = mask & n; System.out.printf("Mask n and result is: %s\n", Integer.toBinaryString(maskN)); // 将 m 右移 i 位,与清零后的n 或 int insertRest = maskN | (m << i); System.out.printf("Insert result is: %s\n", Integer.toBinaryString(insertRest)); return insertRest; }
输出
n: 10000000000000000000000000000000 ; m: 10011 ---------- Build mask ---------- The left of mask is: 11111111111111111111111110000000 The right of mask is: 11 The mask is: 11111111111111111111111110000011 Mask n and result is: 10000000000000000000000000000000 Insert result is: 10000000000000000000000001001100
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序
- 二叉查找树