您的位置:首页 > 编程语言 > Java开发

二进制位运算积累备忘

2016-01-30 13:48 204 查看
java的基本数据类型,以及在内存中所占的位数。(一个字节等于8位)

数据类型所占字节所占位数
byte18
boolean18
short216
int432
long864
float432
double864
char216
十进制转r进制总结:

方法:除r取余,直至商0,余数倒叙排列!

比如67这个数

十进制转换成二进制 采用短除2法;

余数
2\67331
2\33161
2\1680
2\840
2\420
2\210
1\201
商是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

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 位运算 二进制