二进制位运算积累备忘
2016-01-30 13:48
204 查看
java的基本数据类型,以及在内存中所占的位数。(一个字节等于8位)
十进制转r进制总结:
方法:除r取余,直至商0,余数倒叙排列!
比如67这个数
十进制转换成二进制 采用短除2法;
商是0的时结束,将余数从下往上数,即可得到二进制数结果 1000011
二进制转换成十进制 采用科学计数法,按位权展开;
比如上面这个数1000011
1*2^(1-1)+1*2^(2-1)+1*2^(7-1)=1+2+64=67;
二进制的位运算
1,先介绍二进制中几个基本的概念原码,反码,补码:
补充一下所有计算机中这些码可以理解为一种规定标准,就是说计算机里以何种标准来存储二进制;
在计算机中,参与运算的是二进制数的补码形式;
原码:
就是一个数的二进制形式
00000000 00000000 00000000 00001000是8(int)的原码
10000000 00000000 00000000 00001000是-8(int)的原码
其中,最高位为符号位:正数为0,负数为1。剩下的n-1位表示该数的绝对值,
PS:正数的原、反、补码都一样:0的原码跟反码都有两个,因为这里0被分为+0和-0。
反码:
反码就是在原码的基础上,符号位不变其他位按位取反 (就是0变1,1变0)就可以了。
比如x=+8; 00000000 00000000 00000000 00001000
对于负数 它的原码个位数取反 。比如 -8
比如将 10000000 00000000 00000000 00001000 取反
得反码 11111111 11111111 11111111 11110111
补码:
补码就是在反码的基础上+1.
,例如-8表示如下:
8的二进制代码 10000000 00000000 00000000 00001000
所有位取反 后 11111111 11111111 11111111 11110111
末位加上1得补码 11111111 11111111 11111111 11111000(二进制逢2进1)
总结:
正数:
原码=反码=补码
负数:
原码
反码=其原码除符号位之外的各位求反
补码=反码+1 (如果+1之后有进位的,要一直往前进位,包括符号位)
在二进制里面(整型int使用32个字节,32位,其中最高位为0表示的是正数,最高位为1表示的是负数)
其中0含义代表的是false,1含义表示true
在接触位运算符的时候,把1想成true,把0想成false,结果为true代表1,结果为false代表0,
感觉是不是和java逻辑运算符差不多!
&运算
按位与运算 两位都为1,结果才是1;0&0=0;0&1=0;1&0=0;1&1=1
是不是可以理解成两个都为true,结果才是true
按位与运算的应用:
可以判断一个数x的奇偶性(x&1=0,说明x是偶数,x&1=1,说明x是奇数)
保留指定的位数,比如想保留数a的后8位(0xff是16进制,转换二进制00000000 00000000 11111111 1111111)
| 或运算
按位或 只要有一个为1,结果就为1;0|0=0;0|1=1;1|0=1;1|1=1
是不是可以理解成两个中有一个为true,结果就是true
按位或运算的应用;
将一个数x指定位全部换成1
比如上面的a
^ 异或运算
按位异或运算 相应位值不同,则该位结果为1,否则为0;0^0=0;0^1=1;1^0=1;1^1=0
是不是可以理解成两个都不为true或者false时,结果才是true
按位异或的应用:
定位反转 将一个数x的0位变成1,1位变成0
交换a和b的数值
~ 反码
按位取反 将一个位上的数按位取反,即0变成1,1变成0;~1=0 ;~0=1;
是不是可以理解成!true,结果是false,!false,结果是true.
先了解一下下面负数二进制表示形式;上面说了,负数以其正值的补码形式表示
负数以其正值的补码形式表示,补码等于负数绝对值的反码+1
<< 左移
将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)
左移的规律:
一个数y左移n位(y<< n),就相当于这个数乘以2^n;
>>右移
将一个运算对象的各个二进制位全部右移若干位(是正数,左边的二进制位补0,是负数,左边二进制位补1;右边统统舍弃)
右移的规律:
一个数y右移n位(y>> n),就相当于这个数除以2^n;
>>>无符号右移
各个位向右移指定的位数,右移后左边空出的位用零来填充,移除右边的位被舍弃
java中常见的进制转换方法:
判断int型变量a是奇数还是偶数
a&1 = 0 偶数
a&1 = 1 奇数
求平均值,比如有两个int类型变量x、y,首先要求x+y的和,再除以2,但是有可能x+y的结果会超过int的最大表示范围,所以位运算就派上用场啦。
(x&y)+((x^y)>>1);
对于一个大于0的整数,判断它是不是2的几次方
((x&(x-1))==0)&&(x!=0);
比如有两个int类型变量x、y,要求两者数字交换,位运算的实现方法:性能绝对高效
x ^= y;
y ^= x;
x ^= y;
求绝对值
int abs( int x )
{
int y ;
y = x >> 31 ;
return (x^y)-y ; //or: (x+y)^y
}
取模运算,采用位运算实现:
a % (2^n) 等价于 a & (2^n - 1)
乘法运算 采用位运算实现
a * (2^n) 等价于 a << n
除法运算转化成位运算
a / (2^n) 等价于 a>> n
求相反数
(~x+1)
10 a % 2 等价于 a & 1
数据类型 | 所占字节 | 所占位数 |
---|---|---|
byte | 1 | 8 |
boolean | 1 | 8 |
short | 2 | 16 |
int | 4 | 32 |
long | 8 | 64 |
float | 4 | 32 |
double | 8 | 64 |
char | 2 | 16 |
方法:除r取余,直至商0,余数倒叙排列!
比如67这个数
十进制转换成二进制 采用短除2法;
除 | 商 | 余数 |
---|---|---|
2\67 | 33 | 1 |
2\33 | 16 | 1 |
2\16 | 8 | 0 |
2\8 | 4 | 0 |
2\4 | 2 | 0 |
2\2 | 1 | 0 |
1\2 | 0 | 1 |
二进制转换成十进制 采用科学计数法,按位权展开;
比如上面这个数1000011
1*2^(1-1)+1*2^(2-1)+1*2^(7-1)=1+2+64=67;
二进制的位运算
1,先介绍二进制中几个基本的概念原码,反码,补码:
补充一下所有计算机中这些码可以理解为一种规定标准,就是说计算机里以何种标准来存储二进制;
在计算机中,参与运算的是二进制数的补码形式;
原码:
就是一个数的二进制形式
00000000 00000000 00000000 00001000是8(int)的原码
10000000 00000000 00000000 00001000是-8(int)的原码
其中,最高位为符号位:正数为0,负数为1。剩下的n-1位表示该数的绝对值,
PS:正数的原、反、补码都一样:0的原码跟反码都有两个,因为这里0被分为+0和-0。
反码:
反码就是在原码的基础上,符号位不变其他位按位取反 (就是0变1,1变0)就可以了。
比如x=+8; 00000000 00000000 00000000 00001000
对于负数 它的原码个位数取反 。比如 -8
比如将 10000000 00000000 00000000 00001000 取反
得反码 11111111 11111111 11111111 11110111
补码:
补码就是在反码的基础上+1.
,例如-8表示如下:
8的二进制代码 10000000 00000000 00000000 00001000
所有位取反 后 11111111 11111111 11111111 11110111
末位加上1得补码 11111111 11111111 11111111 11111000(二进制逢2进1)
总结:
正数:
原码=反码=补码
负数:
原码
反码=其原码除符号位之外的各位求反
补码=反码+1 (如果+1之后有进位的,要一直往前进位,包括符号位)
在二进制里面(整型int使用32个字节,32位,其中最高位为0表示的是正数,最高位为1表示的是负数)
其中0含义代表的是false,1含义表示true
在接触位运算符的时候,把1想成true,把0想成false,结果为true代表1,结果为false代表0,
感觉是不是和java逻辑运算符差不多!
&运算
按位与运算 两位都为1,结果才是1;0&0=0;0&1=0;1&0=0;1&1=1
是不是可以理解成两个都为true,结果才是true
int a = 8;// 8(10)==00000000 00000000 00000000 00001000(2) int b = 9;// 9(10)==00000000 00000000 00000000 00001001(2) int c = a & b;// == 00000000 00000000 00000000 00001000(2) System.out.println(c);// c=8
按位与运算的应用:
可以判断一个数x的奇偶性(x&1=0,说明x是偶数,x&1=1,说明x是奇数)
System.out.println(a & 1);// 结果0,说明a是偶数 System.out.println(b & 1);// 结果1,说明b是奇数
保留指定的位数,比如想保留数a的后8位(0xff是16进制,转换二进制00000000 00000000 11111111 1111111)
System.out.println(a = a & 0xff);// ==00000000 00000000 00000000 00001000(2) System.out.println(Integer.toBinaryString(a & 0xff));
| 或运算
按位或 只要有一个为1,结果就为1;0|0=0;0|1=1;1|0=1;1|1=1
是不是可以理解成两个中有一个为true,结果就是true
int a = 8;// 8(10)==00000000 00000000 00000000 00001000(2) int b = 9;// 9(10)==00000000 00000000 00000000 00001001(2) int c = a | b;// == 00000000 00000000 00000000 00001001(2) System.out.println(c);// c=9
按位或运算的应用;
将一个数x指定位全部换成1
比如上面的a
//数a的后8位全部变成1 System.out.println(a = a | 0xff);//== 00000000 00000000 00000000 11111111(2) System.out.println(Integer.toBinaryString(a | 0xff));
^ 异或运算
按位异或运算 相应位值不同,则该位结果为1,否则为0;0^0=0;0^1=1;1^0=1;1^1=0
是不是可以理解成两个都不为true或者false时,结果才是true
int a = 8;// 8(10)==00000000 00000000 00000000 00001000(2) int b = 9;// 9(10)==00000000 00000000 00000000 00001001(2) int c = a ^ b;// == 00000000 00000000 00000000 00000001(2) System.out.println(c);// c=1
按位异或的应用:
定位反转 将一个数x的0位变成1,1位变成0
System.out.println(a ^ 0xff);// == 00000000 00000000 00000000 11110111(2) System.out.println(Integer.toBinaryString(a ^ 0xff));
交换a和b的数值
a = a ^ b; b = b ^ a; a = a ^ b; System.out.println(a);// 9 System.out.println(b);// 8
~ 反码
按位取反 将一个位上的数按位取反,即0变成1,1变成0;~1=0 ;~0=1;
是不是可以理解成!true,结果是false,!false,结果是true.
先了解一下下面负数二进制表示形式;上面说了,负数以其正值的补码形式表示
int a = 8;// 8(10)==00000000 00000000 00000000 00001000(2) a = ~a; //运算过程 // 原码 00000000 00000000 00000000 00001000(2) // 取反 11111111 11111111 11111111 11110111(2) 是个负数 // 减一 11111111 11111111 11111111 11110110(2) 得到了负数绝对值的反码 // 取反 00000000 00000000 00000000 00001001(2) 的到了负数的绝对值 //转换十进制 等于 9,所以a=-9; System.out.println(a);//-9
负数以其正值的补码形式表示,补码等于负数绝对值的反码+1
<< 左移
将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)
int a = 8;// 8(10)== 00000000 00000000 00000000 00001000(2) int b = -8;// -8(10)=11111111 11111111 11111111 11111000(2) System.out.println(a << 1);// 00000000 00000000 00000000 00010000(2)==16(10) System.out.println(b << 1);// 11111111 11111111 11111111 11110000(2)==-16(10)
左移的规律:
一个数y左移n位(y<< n),就相当于这个数乘以2^n;
>>右移
将一个运算对象的各个二进制位全部右移若干位(是正数,左边的二进制位补0,是负数,左边二进制位补1;右边统统舍弃)
int a = 8;// 8(10)== 00000000 00000000 00000000 00001000(2) int b = -8;// -8(10)=11111111 11111111 11111111 11111000(2) System.out.println(a >> 1);// 00000000 00000000 00000000 00000100(2)==16(4) System.out.println(b >> 1);// 11111111 11111111 11111111 11111100(2)==-16(4)
右移的规律:
一个数y右移n位(y>> n),就相当于这个数除以2^n;
>>>无符号右移
各个位向右移指定的位数,右移后左边空出的位用零来填充,移除右边的位被舍弃
int a = 8;// 8(10)== 00000000 00000000 00000000 00001000(2) int b = -8;// -(10)=11111111 11111111 11111111 11111000(2) System.out.println(a >>> 1);// 00000000 00000000 00000000 00000100(2)==4(4) System.out.println(b >>> 1);// 01111111 11111111 11111111 11111100(2)==2147483644(4)
java中常见的进制转换方法:
/** 二进制:数字前面加上“0b”例如0b10010 八进制:数字前面加上“0” 例如"0123" 十六进制:数字前面加上“0x" 例如”0x12" */ int num = 0b10010; String str = "10010"; System.out.println(Integer.toBinaryString(num));// 转化为2进制 System.out.println(Integer.toString(num, 2));// 转化为2进制 System.out.println(Integer.toOctalString(num));// 转化为8进制 System.out.println(Integer.toString(num, 8));// 转化为8进制 System.out.println(Integer.toHexString(num));// 转化为16进制 System.out.println(Integer.toString(num, 16));// 转化为16进制 System.out.println(Integer.toString(num));// 转化为10进制 System.out.println(Integer.toString(num, 10));// 转化为10进制 System.out.println("-------------------------------------"); System.out.println(Integer.parseInt(str, 2));// 把2进制数解析成10进制 System.out.println(Integer.parseInt(str, 8));// 把8进制数解析成10进制 System.out.println(Integer.parseInt(str, 10));// 把10进制数解析成10进制 System.out.println(Integer.parseInt(str));// 默认把数看成是10进制,转化为10进制 System.out.println(Integer.parseInt(str, 16));// 把16进制数解析成10进制
判断int型变量a是奇数还是偶数
a&1 = 0 偶数
a&1 = 1 奇数
求平均值,比如有两个int类型变量x、y,首先要求x+y的和,再除以2,但是有可能x+y的结果会超过int的最大表示范围,所以位运算就派上用场啦。
(x&y)+((x^y)>>1);
对于一个大于0的整数,判断它是不是2的几次方
((x&(x-1))==0)&&(x!=0);
比如有两个int类型变量x、y,要求两者数字交换,位运算的实现方法:性能绝对高效
x ^= y;
y ^= x;
x ^= y;
求绝对值
int abs( int x )
{
int y ;
y = x >> 31 ;
return (x^y)-y ; //or: (x+y)^y
}
取模运算,采用位运算实现:
a % (2^n) 等价于 a & (2^n - 1)
乘法运算 采用位运算实现
a * (2^n) 等价于 a << n
除法运算转化成位运算
a / (2^n) 等价于 a>> n
求相反数
(~x+1)
10 a % 2 等价于 a & 1
相关文章推荐
- 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播放器
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序
- 二叉查找树