进制转换
什么是进制
进制也就是进位计数制,是人为定义的带进位的计数方法(有不带进位的计数方法,比如原始的结绳计数法,唱票时常用的“正”字计数法,以及类似的tally mark计数)。 对于任何一种进制—X进制,就表示每一位置上的数运算时都是逢X进一位。 十进制是逢十进一,十六进制是逢十六进一,二进制就是逢二进一,以此类推,x进制就是逢x进位。
Java针对整数变量提供了4种表现形式
-
二进制
-
八进制
-
十进制
-
十六进制
为什么会有二进制、八进制、十六进制
有二进制的原因是因为计算机最底层的电子元器件只有两种状态–高电平和低电平(有电和没电)。任何数据在计算机中都是以二进制的形式存在的,二进制早期由电信号开关演变而来。一个整数在内存中一样也是二进制的,但是使用一大串的1或者0组成的数值进行使用很麻烦!
有八进制、十六进制的原因是因为二进制表示同样的数值太长不方便阅读和记忆,而八进制和十六进制较短,方便阅读和记忆。
ASCII 奥斯卡码值1个字节 八位可以表示256不同个字符
计算机中存储单位的换算
-
8bit=1byte
-
1kb=1024byte
-
1mb=1024kb
-
1gb=1024mb
-
1tb=1024gb
什么是bit?
二进制:001 每一位就是bit,二进制只能是0/1两种数字组成,是计算机中一个最小的信号单位,可能是高电平也可能是低电平
什么是byte?
1个bit只能表示两种信号或者两种状态,表示的范围很小!因为咱们英文字母就有26个,两种状态很明显不够表示。所以国际标准化组织就规定把8个bit归为一组数据的最小单元!
不同进制的组成
-
二进制
- 有0,1组成。以0b开头(不区分大小写)
-
八进制
- 由0,1,2…7组成。以0开头
-
十进制
- 由0,1,2…9组成。整数位默认是十进制的
-
十六进制
- 由0,1,2…,a,b,c,d,e,f(大小写均可)。以0x开头(不区分大小写)
**注意:**进制位计算也是从0开始的
//演示100在各个进制之间的值
public static void main(String[] args) {
int a = 0b100;//二进制
int b = 0100;//八进制
int c = 100;//十进制
int d = 0x100;//十六进制
System.out.println("二进制:"+a+"\t八进制:"+b+"\t十进制:"+c+"\t十六进制:"+d);
//结果为:二进制:4(2^2) 八进制:64(8^2) 十进制:100(默认) 十六进制:256(16^2)
}
不同进制数据之间的计算
十进制数据之间的计算
10+10=20
二进制数据之间的计算
0b1101+0b1101010=0b1110111
八进制数据之间的计算
0127+0765=01114
十六进制数据之间的计算
(a=10,b=11,c=12,d=13,e=14,f=15)
0x1ab+0x99a=0xb45
练习
ob1110111-0b1111010=?
01765-043211=?
0x1fffa-0x2ffab=?
进制转换
-
系数:每一个位上的数字,例如157,个位系数为7、十位系数为7、百位系数为1
-
基数:就是进制数,几进制基数就是几,10进制基数就是10
-
权:一个数据从右往左数,从0开始,对每一位数据进行编号,那么这个编号就是这个位置上的数字的系数
任意进制到十进制的转换
**公式:**这个数据的各个位上的系数乘以基数的权次幂相加的和
-- 任意进制转换成十进制
0b111=1*2^0+1*2^1+1*2^2=1+2+4=7
0110=0*8^0+1*8^1+1*8^2=0+8+64=72
0xabc1=1*16^0+12*16^1+11*16^2+10*16^3=1+192+2816+40960=43969
十进制到其他进制的转换
**公式:**用这个数字除基数取余数,直到商为0,余数反转
-- 把十机制的100转换为其他进制
-- 十进制转二进制
100=0b1100100
-- 十进制转八进制
100=0144
-- 十进制转十六进制
100=0x64
十进制和二进制之间的快速转换
**8421码:**8421码是中国大陆的叫法,8421码是BCD码中最常用的一种。在这种编码方式中每一位二进制代码的1都是代表一个固定数值,把每一位的1代表的十进制数加起来,得到的结果就是它所代表的十进制数码。
**BCD码:**BCD 码(Binary-Coded Decimal〉亦称二进码十进数或二-十进制代码。用4位二进制数来表示1位十进制数中的0~9这10个数码。是一种二进制的数字编码形式,用二进制编码的十进制代码。
BCD码展示:
二进制: | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
---|---|---|---|---|---|---|---|---|
十进制: | 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
二进制和八进制、十六进制如何转换
-
以十进制为桥梁
-
二进制到八进制3位组合
-
二进制到十六进制4位组合
有符号数据表示法
什么是有符号数
所谓有符号数就是数据有正负之分就是有符号数,数据无正负之分就是无符号数。例如:+7、-7就是有符号数
有符号数组成
这里声明一点,必须要记住:计算机存储的数据永远是补码!!!
符号位+数值位(例如:int i=+7)
为什么要有符号数?
因为在计算机中,有符号数有三种表示法:原码、反码和补码。而且所有数据的运算都是采用补码进行的。正数的原码、反码和补码都一样
什么是原码?
就是二进制定点表示法,即最高位为符号位,"0"表示正,"1"表示负,其余为表示数值的大小。
什么是反码?
正数的反码与其原码相同,负数的方法是对其原码逐位取反,但符号位除外。
什么是补码?
补码就是在反码的基础上加1
代码示例
package com.edu.baseAndBitOperations.base;
/**
* 正数和负数是怎么在计算机中进行出储存的
*
* @作者 five-five
* @创建时间 2021/4/16
*/
public class Demo03 {
public static void main(String[] args) {
//+7、-7在计算机中是如何储存的
//有符号数有两部分组成:1.符号位:最高值表示符号,0为正,1为负 2.数值位
//int的范围:-2的31次方~2的31次方-1(因为有一位是符号位)
// int i=7;//+7
//7:0b0000000000,0000000000,0000000001,11
int i=0b00000000000000000000000000000111;
System.out.println(i);
//int j=-7;//-7
//0b10000000000000000000000000000111;
//计算机存储有符号数的时候是按照补码的形式存进去的
//0b10000000000000000000000000000111;不是二进制的补码,而是二进制的原码
//计算机有符号数据都是按照补码的形式存进去的
//正数的原码反码补码都一样,负数的原码反码补码是不一样的
//什么是原码:就是符号位+数值位
//什么是反码:除符号位不变,其他位全部1变0,0变1
//什么是补码:补码就是在反码的基础上加1
/*
+7:
原码:0b0,00000000,00000000,00000000,00001,11
反码:0b0,00000000,00000000,00000000,00001,11
补码:0b0,00000000,00000000,00000000,00001,11
-7:
原码:0b1,00000000,00000000,00000000,00001,11
反码:0b1,11111111,11111111,11111111,11110,00
补码:0b1,11111111,11111111,11111111,11110,01
*/
int j=0b11111111111111111111111111111001;//-7
System.out.println(j);
//计算机在显示给我们看的时候,会把补码转换为原码
//怎么转:补码-1变成反码,剩下的除符号位不变,其余的0变1,1变0
}
}
位运算(位指的是二进制位或者是bit位)
计算机中所有的订算到计算机底层中都会变成位运算(就是二进制位的运算)。位运算可以提高程序的效率!而且以后如果我们研究JDK或者某个框架的原码,会发现很多地方都用到了位运算!
位运算的种类
-
**&**
:按位与,规则:两个同为1时才为1 -
**|**
:按位或,规则:只要上下有一方为1的时候,就等于1 -
**^**
:按位异或,规则:两个中不一样的时候才为1,如果一样就为0 -
**~**
:按位取反,规则:1变0,0变1 -
**<<**
:左移,规则:让操作数乘以2的n次幂,n就是移动的位移 -
**>>**
:右移,规则:让操作数除以2的n次幂,n就是移动的位移 -
**>>>**
:无符号右移,规则:操作数除以2的n次幂,用0补全空位 -
无符号右移
**>>>**
和右移**>>**
的区别是:-
**>>**
右移操作之后左边会有空位置出来且空位置用该操作数的符号位置的数补全 -
**>>>**
无符号右移之后左边会有空位置出来且空位置用0补全
-
注意:进行位运算的时候,所有的操作数全部都是二进制,并且是补码!!!
代码示例
&、|、、~位运算符的操作和理解,(按位与&、按位或|、按位异或、按位取反~)
package com.edu.baseAndBitOperations.base;
/**
* 位运算符的操作和理解,(按位与&、按位或|、按位异或^、按位取反~)
* 注意:进行位运算的时候,所有的操作数全部都是二进制,并且是补码!!!
*
* @作者 five-five
* @创建时间 2021/4/16
*/
public class Demo04 {
/*
&:按位与,只有上下都为1的时候,才等于1
|:按位或,只要上下有一方为1的时候,就等于1
^:按位异或,两个中不一样的时候才为1,如果一样就为0
~:按位取反,1变0,0变1
<<:左移,让操作数乘以2的n次幂,n就是移动的位移
>>:右移,让操作数除以2的n次幂,n就是移动的位移
>>>:无符号右移,操作数除以2的n次幂,用0补全空位
*/
public static void main(String[] args) {
//注意:在进行位运算时时候要把数据转换成二进制位!并且全部都是二进制的补码形式。
//按位与:&,只有上下都为1的时候,才等于1
//3&4的结果
//3:0b0000000000,0000000000,0000000000,11
//4:0b0000000000,0000000000,0000000001,00
//3&4:0b0000000000,0000000000,0000000000,00
System.out.println(3 & 4);//0
//注意:在进行位运算时时候要把数据转换成二进制位!并且全部都是二进制的补码形式。
//按位或:|,只要上下有一方为1的时候,就等于1
//3|4的结果
//3:0b0000000000,0000000000,0000000000,11
//4:0b0000000000,0000000000,0000000001,00
//3|4:0b0000000000,0000000000,0000000001,11
System.out.println(3 | 4);//7
//注意:在进行位运算时时候要把数据转换成二进制位!并且全部都是二进制的补码形式。
//按位异或:^,两个中不一样的时候才为1,如果一样就为0
//3^4的结果
//3:0b0000000000,0000000000,0000000000,11
//4:0b0000000000,0000000000,0000000001,00
//3^4:0b0000000000,0000000000,0000000001,11
System.out.println(3 ^ 4);//7
//注意:在进行位运算时时候要把数据转换成二进制位!并且全部都是二进制的补码形式。
//按位取反:~,1变0,0变1
//~4的结果
//4:0b0000000000,0000000000,0000000001,00
//~4:0b11111111111111111111111111111110,11(相当于补码)
//反码:0b11111111111111111111111111111110,10(补码-1=反码)
//源码:0b10000000000000000000000000000001,01(反码取反=原码)
System.out.println(~4);//-5
}
}
按位异或的常见应用
package com.edu.baseAndBitOperations.base;
/**
* ^:按位异或,两个中不一样的时候才为1,如果一样就为0
* 按位异或^的常见应用:一个数据对相同的数据异或两次其值不变
*
* @作者 five-five
* @创建时间 2021/4/16
*/
public class Demo05 {
public static void main(String[] args) {
/*
数据a
数据b
a两次异或b 结果还是a
a^b^b=a
*/
int a = 2;
int b = 3;
//2:0b00000000,00000000,00000010
//3:0b00000000,00000000,00000011
//a=2^3:0b00000000,00000000,00000001
//a^3:0b00000000,00000000,00000010
int temp = a ^ b;
temp ^= b;
System.out.println(a ^ b ^ b);
System.out.println(temp);
}
}
<<、>>、>>>位运算符的操作和理解,(左移<<、右移>>、无符号右移<<<)
package com.edu.baseAndBitOperations.base;
/**
* 位运算符的操作和理解,(左移<<、右移>>、无符号右移<<<)
* 注意:进行位运算的时候,所有的操作数全部都是二进制,并且是补码!!!
*
* @作者 five-five
* @创建时间 2021/4/16
*/
public class Demo06 {
/*
&:按位与,只有上下都为1的时候,才等于1
|:按位或,只要上下有一方为1的时候,就等于1
^:按位异或,两个中不一样的时候才为1,如果一样就为0
~:按位取反,1变0,0变1
<<:左移,让操作数乘以2的n次幂,n就是移动的位移
>>:右移,让操作数除以2的n次幂,n就是移动的位移
>>>:无符号右移,操作数除以2的n次幂,
无符号右移和右移的区别是:
右移操作之后左边会有空位置出来且空位置用该操作数的符号位置的数补全
无符号右移之后左边会有空位置出来且空位置用0补全
格式:操作数<<往左移动的位数
操作数>>往右移动的位数
操作数>>>往右移动的位数
*/
public static void main(String[] args) {
//左移 <<
int i = 3;
//3:0b00000000,00000000,00000000,00000011
//3<<2:0b000000,00000000,00000000,0000001100(往左边移动两位,左边的两位就被挤掉了,右边就空出两位用0补全)
System.out.println(i << 2);//3*2^2
//右移 >>
int j = 32;
//32:0b00000000,00000000,00000000,00100000
//32>>2:0b00000000,00000000,00000000,00001000(往右边移动两位,左边就空出两位,右边的两位就被挤掉了,左边空出的位置用符号位的值填充)
System.out.println(j >> 2);//32/(2^2)
//-32:0b10000000,00000000,00000000,00100000(原码)
//-32:0b11111111,11111111,11111111,11011111(反码)
//-32:0b11111111,11111111,11111111,11100000(补码)
//-32>>2:0b11111111,11111111,11111111,11100000
//(往右边移动两位,左边就空出两位,右边的两位就被挤掉了,左边空出的位置用符号位的值填充)
//-32>>2:0b1111111111,11111111,11111111,111000(补码)
//-32>>2:0b1111111111,11111111,11111111,110111(反码)
//-32>>2:0b1000000000,00000000,00000000,001000(原码)
System.out.println(-j >> 2);//-32/(2^2)
System.out.println(0b11111111111111111111111111111000);//-32/(2^2)
//无符号右移 >>>
int k = 32;
//32:0b00000000,00000000,00000000,00100000
//32>>>2:0b00000000,00000000,00000000,00001000(往右边移动两位,左边就空出两位,右边的两位就被挤掉了,左边空出的位置用0填充)
System.out.println(k >>> 2);//32/(2^2)
//-32:0b10000000,00000000,00000000,00100000(原码)
//-32:0b11111111,11111111,11111111,11011111(反码)
//-32:0b11111111,11111111,11111111,11100000(补码)
//32>>>2:0b0011111111,11111111,11111111,111000(往右边移动两位,左边就空出两位,右边的两位就被挤掉了,左边空出的位置用0填充)
System.out.println(-k >>> 2);
System.out.println(0b00111111111111111111111111111000);
}
}