Java进制转换和位运算
1.常见进制的组成
二进制:由0和1组成
八进制:由0,1,2,3,4,5,6,7组成
十六进制:由0到9,外加A,B,C,D,E,F六个英文字母(不分大小写)组成,A相当于十进制中的10,B是11,C是12,D是13,E是14,F是15
2.表达形式
二进制的写法:以0b开头
八进制的写法:以0开头
十六进制的写法:以0x开头
3.计算方法
规则:是几进制则满几进一,例如十进制是满十进一,二进制则是满二进一,八和十六进制同理。
例如:
二进制:0b11110+0b111001=?
1 1 1 1 0
+ 1 1 1 0 0 1
----------------------
1 0 0 1 0 0 0 0
= 0b10010000
八进制:01234+05678=?
1 2 3 4
+ 5 6 7 8
----------------------
7 1 3 4
= 07134
十六进制:0x3ac+0x8bf6=?
3 a c 3 10 12
+ 8 b f 6 =》同等于 + 8 11 15 6 =》 用十六进制表示为:0x8fa2
---------------------- ----------------------
8 15 10 2
=0x8fa2
4.任意进制转换为十进制的方法
概念说明:
- 系数:是指每一位上的数,例如十进制123,个位上的系数为3,十位上的系数为2,百位上的系数为1,其他进制同理;
- 基数:是几进制基数就是几,例如二进制的基数为2,十进制的基数为10;
- 权:一个数从右往左数,位置从0开始数,每一位数所在的位置就是该位的权,例如:十进制1234567,7的权是0, 6的权是1,5的权是2,4的权是3,类似于String的index;
具体方法(规律):任意进制转换为十进制都等于“ 这个数的每一位的系数乘以基数的权次幂的和 ”。
例如:
十进制->十进制:456 = 6*10^0 + 5*10^1 + 4*10^2 = 6+50+400 = 456
二进制->十进制:0b456 = 6*2^0 + 5*2^1 + 4*2^2 = 6+10+16 = 32
八进制->十进制:0456 = 6*8^0 + 6*8^1 + 4*8^2 = 6+48+256 = 310
十六进制->十进制:0x456 = 6*16^0 + 5*16^1 + 4*16^2 = 6+80+1024 = 1110
5.十进制转换为二、八、十六进制
具体方法(规律):十进制转换为任意进制,都是除以基数取余,直到商为0,然后对余数进行反转
例如:
十进制100->二进制
2|___100__ 0 ∧
2 |___50____ 0 ∧
2 |____25_____ 1 ∧
2 |____12____ 0 ∧
2|____6___ 0 ∧
2|____3____ 1 ∧
2|___1____ 1 ∧
0
描述:把所有余数进行组合->0010011->进行反转->1100100,也就是从下往上进行组合的顺序,所以最后表示结果为:0b1100100
十进制100->八进制
8|___100__ 4 ∧
8 |___12____ 4 ∧
8 |____1_____ 1 ∧
0
描述:把所有余数进行组合->441->进行反转->144,也就是从下往上进行组合的顺序,所以最后表示结果为:0441
十进制200->十六进制
16|___200__ 8 ∧
16 |___12____ 12 ∧
0
描述:把所有余数进行组合->8c(12用字母c来代替)->进行反转->c8,也就是从下往上进行组合的顺序,所以最后表示结果为:0xc8
6.二进制中的有符号数和无符号数
数据有正负之分的属于有符号数,没有正反之分的属于无符号数
例如:1和-1等属于有符号数(数字有正负之分),表示正一和负一,类似文件之类的数据,视频和音频等属于无符号数,没有正负之分
有符号数由两部分(符号位+数值位)组成:
- 符号位:正为0,负为1,用最高位(从左往右,第一位)来表示符号位;
- 数值位:符号位之后的就为数值位
7.有符号数的原码、反码和补码
计算机中,有符号数是以补码的形式进行存储,以原码的形式展示出现,正数的原码、反码和补码都是一样的,负数的原
码、反码和补码是不一样的,存储和展示的时候会对其进行相互转换。
注:(平常其他进制转化为二进制时,如(除2取余),转换之后都是以原码的形式来体现的)
转换规则如下:
原码->反码->补码
原码->反码:符号位不变,其他位0变1 1变0
反码->补码:反码加1得到补码
反之:补码->反码->原码
补码->反码:补码减一得到反码
反码->原码:符号位不变,其他位0变1 1变0
例如:
正数7的原码为:0b00000000 00000000 00000000 00000111(int类型占4个字节,1个字节是8位),
符号位为0,正数原反补码一样,所以反码和补码也为0b00000000 00000000 00000000 00000111,
而负数-7的原码为:0b10000000 00000000 00000000 00000111,存储时会将原码转换为补码进行存储,
由-7原码可得:
原码->反码:0b11111111 11111111 11111111 11111000 ,得到反码(符号位不变,其他位0变1 1变0)
再由反码->补码:0b11111111 11111111 11111111 11111001(反码加1得到补码)
所以 7在内存中存储的值0b00000000 00000000 00000000 00000111 (补码形式)
-7在内存中存储的值0b11111111 11111111 11111111 11111001 (补码形式)
8.位运算(对数字计算而言)符号
- &:按位与
- | :按位或
- ^:按位异或
- ~:按位取反
- <<:左移
- >>:右移
- >>>:无符号右移
在进行位运算的时候,需要先把数据先转换成二进制位,并且都是以二进制的补码形式进行操作
例如:
4的二进制为:0b00000000 00000000 00000000 00000100(正数原反补码都一样,在此表示为补码形式)
6的二进制为:0b00000000 00000000 00000000 00000110(正数原反补码都一样,在此表示为补码形式)
(1)按位与规则:两个同时为1,则为1,否则为0
4 & 6 = 0b00000000 00000000 00000000 00000100(补码形式) = 0*2^0+0*2^1+1*2^2 = 4(在此表示为原码形式)
(2)按位或规则:一个为1,则为1,否则为0
4 | 6 = 0b00000000 00000000 00000000 00000110(补码形式) = 0*2^0+1*2^1+1*2^2 = 6(在此表示为原码形式)
(3)按位异或规则:两个不一样的时候为1,否则为0
4 ^ 6 = 0b00000000 00000000 00000000 00000010(补码形式) = 0*2^0+1*2^1 = 2(在此表示为原码形式)
(4)按位取反规则:0变1,1变0
~4 = 0b11111111 11111111 11111111 11111011(补码形式),可以看出最高位1,所以结果为负数,
需要把结果由补码转为反码,然后反码转为原码即可得出最后结果,因此:
(1)0b11111111 11111111 11111111 11111011(补码形式)
(2)转为反码:0b11111111 11111111 11111111 11111010(反码形式)
(3)由反码转为原码:0b10000000 00000000 00000000 000000101(原码形式) = -(1*2^0+0*2^1+1*2^2)=-(1+4)=-5
~6同理,结果为:~6 = 0b11111111 11111111 11111111 11111001(补码形式)
-> 转反码: = 0b11111111 11111111 11111111 11111000(反码形式)
-> 转原码: = 0b10000000 00000000 00000000 00000111(原码形式) = -(1*2^0+1*2^1+1*2^2)=-(1+2+4)=-7
(5)按位左移规则:操作数乘以2的n次幂,n为左移的位数
具体操作方式:左移几位,就将二进制位向左移动几位,舍弃移除的位数,然后右边空出的位用0填补
例如4的二进制为:0b00000000 00000000 00000000 00000100(正数原反补码都一样,在此表示为补码形式)
4 << 6
->将4的二进制的补码左移6位-> 0b00000000 00000000 00000001 00->右边空出的位补0
-> 0b00000000 00000000 00000001 00000000->判断符号位是0还是1
->符号位(最高位)为0是正数,所以不用进行码转换操作(正数原反补码都一样,在此表示为原码形式)
-> = 0*2^0+0*2^1+0*2^2+0*2^3+0*2^4+0*2^5+0*2^6+0*2^7+1*2^8 = 2^8= 256(也就是4乘以2的6次方)
(6)按位右移规则:操作数(正数)除以2的n次幂,n为右移的位数
具体操作方式:右移几位,就将二进制位向右移动几位,舍弃移除的位数,然后左边空出的位由符号位来决定,
符号位为0,则用0填补,符号位为1,则用1填补
例如4的二进制为:0b00000000 00000000 00000000 00000100(正数原反补码都一样,在此表示为补码形式)
4 >> 6
->将4的二进制的补码右移6位-> 0b00000000 00000000 00000000 00
->判断符号位是0还是1
->符号位(最高位)为0(右移 符号位为0,则用0填补,符号位为1,则用1填补)
->0b00000000 00000000 00000000 00000000->最高位为0是正数,所以不用进行码转换操作(正数原反补码都一样,在此表示为原码形式)->
-> = 0 (也就是4除以2的6次方)
对负数进行左移或者右移操作方式如下:
规则:因为位移操作都是以二进制的补码形式进行操作的,所以首先需要得到负数的原码之后,再求的补码,才能对其进行位操作。
例如-4的二进制为:0b10000000 00000000 00000000 00000100(在此表示为原码形式)
原码->反码:0b11111111 11111111 11111111 11111011
反码->补码:0b11111111 11111111 11111111 11111100
求得-4的二进制补码形式为:0b11111111 11111111 11111111 11111100
(1)-4 << 6
->将-4的二进制的补码左移6位
->0b11 11111111 11111111 11111100->判断符号位是0还是1->符号位(最高位)为1
->0b11111111 11111111 11111111 00000000(补码形式)->最高位为1是负数,所以需要转换成反码的形式
->0b11111111 11111111 11111110 11111111(反码形式)
->0b10000000 00000000 00000001 00000000(原码形式)
-> = -(0*2^0+0*2^1+0*2^2+0*2^3+0*2^4+0*2^5+0*2^6+0*2^7+1*2^8) = -1*2^8 = -256 (也就是-4乘以2的6次方)
(2)-4 >> 6
->将-4的二进制的补码右移6位-> 0b11111111 11111111 11111111 11->判断符号位是0还是1->符号位(最高位)为1
->(右移 符号位为0,则用0填补,符号位为1,则用1填补)
->0b11111111 11111111 11111111 11111111(补码形式)->最高位为1是负数,所以需要转换成反码的形式
->0b11111111 11111111 11111111 11111110(反码形式)
->0b10000000 00000000 00000000 00000001(原码形式)
-> = -(1*2^0) = -1
(7)按位无符号右移:
具体操作方式与右移规则一样,与右移操作符的区别在于,右移的空位有符号位来决定,符号位为0,则用0填补,符号位为1,则用1填补,而无符号右移,
左边空出的位则全都由0来填补,不由符号位决定
例如-4 >>> 6
->将-4的二进制位右移6位-> 0b11111111 11111111 11111111 11
->(空位由0来填补)
-> 0b00000011 11111111 11111111 11111111(补码形式)
->最高位为0是正数,所以不用进行码转换操作(正数原反补码都一样,在此表示为原码形式)
-> = 1*2^0+1*2^1+1*2^2+1*2^3+1*2^4+1*2^5+1*2^6+...+1*2^25 = 67108863
由此可见,对于正数来说,右移和无符号右移是没区别的,对于负数有些是不能用算术右移来实现除法(例如-32 >> 2 就符合除法规则结果为-8)
以上是最近学习位运算的一些总结,如上述代码有错误之处,还请指出,再次感谢!!