进制转换与位运算
进制转换
- 二进制数:由前缀0b开头,前缀可省略。只有0和1组成
- 十进制数:由1-9开头,0-9组成
- 八进制数:由前缀0以及后续的0-7的数字来表现
- 十六进制数:由前缀0x,反面跟随0-9或大/小写的a-f来表现(a-f依次表现10-15)
数学进制转换
十进制 => 二进制
十进制数除2取余法,即十进制数除2,余数为权位上的数,得到的商值继续除2,依此步调继续向下运算直到商为0为止。
十进制160804020105210除2取余000001010倒序后:
- 十进制160 的二进制:10100000
- 十进制80 的二进制:1010000
- 十进制40 的二进制:101000
二进制 => 十进制
把二进制数按权展开、相加即得十进制数。
二进制10100000按权展开1 × \times × 270 × \times × 261 × \times × 250 × \times × 240 × \times × 230 × \times × 220 × \times × 210 × \times × 20盘算12803200000相加后:
- 二进制10100000 的十进制 :128 + 32 = 160
- 二进制 100000 的十进制:32
二进制 => 八进制
从右向左,每3位二进制数按权展开相加得到1位八进制数
二进制10100000按权展开 1 × 27 0 × 26 1 × 25 0 × 24 0 × 23 0 × 22 0 × 21 0 × 20盘算240 相加后:
- 二进制10100000 的八进制:240
- 二进制 100000 的八进制:40
八进制 => 二进制
八进制是取三合一,八进制数通过除2取余法,得到二进制数,对每个八进制为3个二进制,不敷时在最左边补零。
八进制240除2 2 1 0 4 2 1 0 0 0取余(二进制) 0 1 0 0 0 1 0 0 0倒序010100000 转换后:
- 八进制240 的 二进制:010100000
- 八进制 40 的二进制:100000
二进制 => 十六进制
与二进制转八进制方法近似,十六进制是取四合一。(注意事项,4位二进制转成十六进制是从右到左开始转换,不敷时补0)
二进制10100000按权展开 1 × 27 0 × 26 1 × 25 0 × 24 0 × 23 0 × 22 0 × 21 0 × 20盘算a(10)0 转换后:
- 二进制10100000 的十六进制:0xa0
- 二进制1010 的十六进制:0xa
十六进制 => 二进制
十六进制数通过除2取余法,得到二进制数,对每个十六进制为4个二进制,不敷时在最左边补零。
十六进制a(10)0除2 10 5 2 1 0 0 0 0 取余 0 1 0 1 0 0 0 0 倒序10100000 转换后:
- 十六进制0xa0的二进制:10100000
- 十六进制0xa 的二进制:1010
【原码、补码、反码】 | 正数:正数的原码即为其反码,正数的原码即为其补码 |
- 十进制:160 --> 二进制:1010 0000
- 原码:0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0
- 反码:0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0
- 补码:0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0
| 负数:将原码除符号位以外的位数取反得到反码,补码=反码+1 |
- 十进制:-160
- 原码:1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0
- 反码:1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 0 1 1 1 1 1
- 补码:1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 0 0 0 0 0
| Java进制转换
- System.out.println("---------------------------------");System.out.println("十进制转二进制:" + Integer.toBinaryString(160));System.out.println("十进制转八进制:" + Integer.toOctalString(160));System.out.println("十进制转十六进制:" + Integer.toHexString(160));System.out.println("十进制转三进制:" + Integer.toString(160,3));System.out.println("---------------------------------");System.out.println("二进制转十进制:" + Integer.parseInt("10100000", 2));System.out.println("八进制转十进制:" + Integer.parseInt("240", 8));System.out.println("十六进制转十进制:" + Integer.parseInt("a0", 16));System.out.println("三进制转十进制:" + Integer.parseInt("12221", 3));System.out.println("---------------------------------");System.out.println("二进制 0b10100000 的十进制:" + 0b10100000);System.out.println("八进制 0024 的十进制:" + 0240);System.out.println("十六进制 0xa0 的十进制:" + 0xa0);System.out.println("---------------------------------");
复制代码
- 数字的二进制表现形式称为“有效的二进制补码”
- java中 Integer.toBinaryString(i) 是转换为二进制补码
按位运算
与(&)
- 如果两个输入位都是1,则按位与,生成一个输出位1;否则生成一个输出位0
1 & 1 = 1 | 1 & 0 = 0 | 0 & 0 = 0 | 或(|)
- 如果两个输入位里只要有一个是1,则按位或,生成一个输出位1;只有在两个输出位都是0的情况下,才会生成一个输出位0。
1 | 1 = 1 | 1 | 0 = 1 | 0 | 0 = 0 | 异或(^)
- 如果输入位的某一个是1,但不全都是1,那么按位异或,生成一个输出位1。
1 ^ 1 = 0 | 1 ^ 0 = 1 | 0 ^ 0 = 0 | i ^ 1 == i + 1 ( i 为偶数) | i ^ -1 == - ( i + 1 ) | i ^ 0 = i | 非(~)
- 按位非,取反操纵符,一元操纵符,只对一个操纵数举行操纵,生成与输入位相反的值
1 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 | ~1 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 | -5 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 | ~-5 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 | a % 2 == a & 1 ; ~x + 1 可得相反数
左移()
- 右移 位操纵符 可以大概按照操纵符右侧指定的位数 将操纵符左边的操纵数 向右 移动
- 规则:溢出的舍弃,空位正数用0填补,负数用1填补
- 注意:移位时,需要使用补码举行盘算
- 盘算负数时,先算出补码举行盘算,盘算完成后,使用补码-1举行逆运算得到反码,最后盘算出原码
无符号右移(>>>)
- 无符号右移:正数与右移规则一样,负数的无符号右移,就是相应的补码移位所得,在高位补0即可
- 对于负数,无符号右移后,不取原码,因此 -10>>>2的效果为111111111111111111111111111101
快捷盘算方式:
对于 i > n,盘算方式是 i / (2n)
位运算应用
1. 判定奇偶性
奇数都不是2的整数倍,转换成二进制后最低位一定为1,偶数则相反。
- boolean isOddNumber(int n){ return (n & 1) == 1;}
复制代码 2. 判定一个正整数是否是2的整数次幂
常见的2的整数次幂的数:2、4、8、16,转化成二进制依次为:10、100、1000、10000。除了首位是1,其他全是0。
规律:这些数减去1后便是他们依次按位取反的效果,好比8-1=7,7的二进制是111,8的二进制1000按位取反后也是111。8 & 7= 0。可总结为 ( n & (n-1))==0
- boolean isPowOfTwo(int n){ return (n & (n-1)) == 0;}
复制代码 3. 求绝对值
任何正数右移31后只剩符号位0,最终效果为0,任何负数右移31后也只剩符号位1,溢出的31位截断,空出的31位补符号位1,最终效果为-1.右移31操纵可以取得任何整数的符号位。
a>>31取得a的符号,若a为正数,a>>31便是0,a ^ 0=a,稳定;若a为负数,a>>31便是-1 ,a ^ -1每一位取反
- int getAbs(int a){ return (a^(a>>31))-(a>>31);}
复制代码 4. 求均匀值
对于两个整数x,y,假设用 (x+y)/2 求均匀值。会产生溢出。由于 x+y 大概会大于INT_MAX,但是它们的均匀值是肯定不会溢出的。
- int getAverage(int x, int y){ return (x&y)+((x^y)>>1); }
复制代码 5. 求二进制中1的个数
一个int型的十进制正整数,盘算出该int型数据在内存中存储时1的个数。
- int getCount(int num){ int count = 0; while(num != 0) { count++; num = num & (num -1); } return count;}
复制代码 来源:https://blog.csdn.net/qq_42002006/article/details/111885433
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |