一、进制转换
1、什么是进制
进制是数学中的一个概念,就是数据“逢几进位”。进制就是进位制,是人们规定的一种进位方法。对于任何一种进制X,就表示某一位置上的数运算时逢X进一位。二进制就是逢二进一,八进制就是逢八进一,十进制就是逢十进一,十六进制就是逢十六进一。
Java中对整数常量提供了4种表现形式:二进制、八进制、十进制、十六进制。
2、为什么有二进制、八进制、十六进制
有二进制的原因是因为计算机最底层的电子元器件只有两种状态——高电平和低电平(有电和没电)。任何数据在计算机中都是以二进制的形式存在的,二进制早期由电信号开关演变而来的。一个整数在内存中一样也是二进制的,但是使用一大串的1或者0组成的数值进行使用很麻烦!有八进制、十六进制的原因是二进制表示同样的数值太长不方便阅读和记忆,二八进制和十六进制较短,方便阅读和记忆。
3、计算机中存储单位的换算
bit(比特):二进制每一位都是一个bit,二进制只能是0或1两个数字组成,比特是计算机中一个最小的信号单位。
byte(字节):一个bit只能表示两种信号或者两种状态,表示的范围很小!英文字母就有26个,还有标点符号,所以国际化标准组织就规定8个bit为一组,用来表示一个信息单元,是最小的信息单位。
8bit = 1byte
1kb = 1024byte
1mb = 1024kb
1gb = 1024mb
1tb = 1024gb
4、不同进制的组成
二进制是由0,1组成。以0b开头。
八进制是由0~7组成,以0开头。
十进制是由0~9组成,整数默认是十进制的1。
十六进制是由0~9和a~f(大小写都可以),以0x开头。(a=10,b=11,c=12,d=13,e=14,f=15)
public class Test1 {
public static void main(String[] args) {
int a = 100;
System.out.println(a);
System.out.println("------------------------------");
int b = 0b100;
System.out.println(b);
System.out.println("------------------------------");
int c = 0100;
System.out.println(c);
System.out.println("------------------------------");
int d = 0x100;
System.out.println(d);
System.out.println("------------------------------");
}
}
5、任意进制转十进制
先了解几个概念:
系数:每一个位上的数字(如:157,个位上的系数是7,十位上的系数是5,百位上的系数是1)。
基数:几进制的基数就是几(十进制的基数就是10)。
权:一个数据从右往左数,从0开始,对每一位数据进行编号,这个编号就是这个位置上的数字的权。
任意进制转十进制的规律:
如二进制(0b110)转为十进制: 0 ∗ 2 0 + 1 ∗ 2 1 + 1 ∗ 2 2 = 0 + 2 + 4 = 6 0*2^0 + 1*2^1 + 1*2^2 = 0 + 2 + 4 = 6 0∗20+1∗21+1∗22=0+2+4=6
如八进制(0110)转为十进制: 0 ∗ 8 0 + 1 ∗ 8 1 + 1 ∗ 8 2 = 0 + 8 + 64 = 72 0*8^0 + 1*8^1 + 1*8^2 = 0 + 8 + 64 = 72 0∗80+1∗81+1∗82=0+8+64=72
如十六进制(0XABC)转为十进制: 12 ∗ 1 6 0 + 11 ∗ 1 6 1 + 10 ∗ 1 6 2 = 12 + 176 + 2560 = 2748 12*16^0 + 11*16^1 + 10*16^2 = 12 + 176 + 2560 = 2748 12∗160+11∗161+10∗162=12+176+2560=2748
6、十进制转任意进制
规律:十进制数除目标基数取余数,直到商为0,余数反转。
如十进制(100)转为二进制:
如十进制(100)转为八进制:
如十进制(200)转为十六进制:
7、其他进制之间转换
以十进制作为桥梁,进行转换。如想将二进制转为八进制的步骤:
二、有符号数据表示法
1、有符号数定义
就是数据有正负之分就是有符号数,数据无正负之分就是无符号数据。如:+7、-7就是有符号数。
2、有符号数的组成
符号位 + 数值位(如:int i = +7;在计算机中表示
0 0000000000000000000000000000111
),java中int占4byte也就是32bit,左边第一位表示符号位,后面都表示数值位。
public class Test1 {
public static void main(String[] args) {
//+7的二进制位
int i = 0b00000000000000000000000000000111;
System.out.println(i);
/**
* 根据符号位表示正负可知,-7的二进制位是0b10000000000000000000000000000111,
* 但是输出的结果却是-2147483641,这是因为计算机中存储有符号数的时候是按照补码
* 形式存储的。
*/
int j = 0b10000000000000000000000000000111;
System.out.println(j);
}
}
3、为什么要有有符号数
因为在计算机内,有符号数有三种表示法
原码、反码、补码
。而且所有数据的运算都是采用补码进行的。
4、什么是原码
就是二进制定点表示法,即最高位为符号位,
0
表示正,1
表示负,其余位表示数值的大小。
注意:正数的原码、反码、补码都是一样的;负数的原码、反码、补码是不一样的。
5、什么是反码
反码就是除符号位不变,其它位全部0变为1,1变为0。
正数的反码与其原码相同,负数的反码是对其原码逐位取反。
6、什么是补码
补码就是在反码的基础上+1就是补码。
+7的原码为:0b00000000000000000000000000000111
+7的反码为:0b00000000000000000000000000000111
+7的补码为:0b00000000000000000000000000000111
-7的原码为:0b10000000000000000000000000000111
-7的反码为:0b11111111111111111111111111111000
-7的补码为:0b11111111111111111111111111111001
public class Test1 {
public static void main(String[] args) {
//+7的二进制位
int i = 0b00000000000000000000000000000111;
System.out.println(i);
/**
* 根据符号位表示正负可知,-7的二进制位是0b10000000000000000000000000000111,
* 但是输出的结果却是-2147483641,这是因为计算机中存储有符号数的时候是按照补码
* 形式存储的。
*/
// -7的原码为:0b10000000000000000000000000000111
// -7的反码为:0b11111111111111111111111111111000
// -7的补码为:0b11111111111111111111111111111001
int j = 0b11111111111111111111111111111001;
/**
* 计算机在显示的时候,会把补码转为原码,转换步骤如下:
* 1、先将补码-1得到反码
* 2、反码除符号位不变,其他为0变1,1变0,得到原码
*/
System.out.println(j);
}
}
三、位运算
1、位运算概述
位指的是二进制位或者是bit位。计算机中所有的计算到计算机底层中都会变成位运算(就是二进制位的运算)。位运算可以提高程序的效率。
2、位运算符的种类
位运算符连接的操作数是数值类型(底层是二进制),位运算表达式的结果仍然是数值类型。
&:按位与
两个同为1的时候结果才为1,否则结果为0。
|:按位或
两个中只要有一个1,那么结果就为1,否则结果为0。
^:按位异或
两个不一样的时候结果才为1,如果一样,结果就为0。一个数异或两次值不变。
~:按位取反
与逻辑非是一样的,1变为0,0变为1。
<<:左移
符号位保留不变,数据位左移几位,低位补0。字面上也就是操作数乘以2的n次幂。
>>:右移
符号位保留不变,数据位右移几位,高位补符号位,即正数补0,负数补1。除2的n次幂。
>>>:无符号右移
数据位右移几位,左边空位都补0(包括符号位),负数会变成正数。注意:
&、|、^
是双目运算符,操作数有两个;~
是单目运算符,操作数只有一个。
public class Test2 {
public static void main(String[] args) {
/**
* 按位与:3 & 4结果是多少
* 在进行位运算的时候要把数据转为二进制位,并且全部都是二进制补码形式!
* 3的二进制:0b00000000000000000000000000000011
* 4的二进制:0b00000000000000000000000000000100
* 3&4: 0b00000000000000000000000000000000
*/
System.out.println("3 & 4 = " + (3 & 4));
/**
* 按位或:3 | 4结果是多少
* 在进行位运算的时候要把数据转为二进制位,并且全部都是二进制补码形式!
* 3的二进制:0b00000000000000000000000000000011
* 4的二进制:0b00000000000000000000000000000100
* 3|4: 0b00000000000000000000000000000111
*/
System.out.println("3 | 4 = " + (3 | 4));
/**
* 按位异或:3 ^ 4结果是多少
* 在进行位运算的时候要把数据转为二进制位,并且全部都是二进制补码形式!
* 3的二进制:0b00000000000000000000000000000011
* 4的二进制:0b00000000000000000000000000000100
* 3^4: 0b00000000000000000000000000000111
*/
System.out.println("3 ^ 4 = " + (3 ^ 4));
/**
* 按位取反:~3是多少
* 在进行位运算的时候要把数据转为二进制位,并且全部都是二进制补码形式!
* 3的二进制:0b00000000000000000000000000000011
* ~3: 0b11111111111111111111111111111100 负数
* 已知补码求原码:补码-1之后取反
* 补码:0b11111111111111111111111111111100
* - 1
* ---------------------------------------
* 反码:0b11111111111111111111111111111011
* 原码:0b10000000000000000000000000000100
*/
System.out.println("~3 = " + (~3));
}
}
左移运算:
public class Test3 {
public static void main(String[] args) {
/**
* 左移:3<<2
* 在进行位运算的时候要把数据转为二进制位,并且全部都是二进制补码形式!
* 规则:符号位会被保留,数据位左移两位,低位补0
* 3的二进制:0b00000000000000000000000000000011
* 3<<2: 0b00000000000000000000000000001100
*/
System.out.println("3 << 2 = " + (3 << 2));
System.out.println(0b00000000000000000000000000001100);
/**
* 左移:-3<<2
* 在进行位运算的时候要把数据转为二进制位,并且全部都是二进制补码形式!
* 规则:符号位会被保留,数据位左移两位,低位补0
* -3的原码: 0b10000000000000000000000000000011
* -3的反码: 0b11111111111111111111111111111100
* -3的补码: 0b11111111111111111111111111111101
* -3<<2: 0b11111111111111111111111111110100
*/
System.out.println("-3 << 2 = " + (-3 << 2));
System.out.println(0b11111111111111111111111111110100);
}
}
右移运算
public class Test4 {
public static void main(String[] args) {
/**
* 右移:3>>2
* 在进行位运算的时候要把数据转为二进制位,并且全部都是二进制补码形式!
* 规则:符号位保留不变,数据位右移2位,高位补符号位
* 3的二进制:0b00000000000000000000000000000011
* 3>>2: 0b00000000000000000000000000000001
*/
System.out.println("3 >> 2= " + (3 >> 2));
System.out.println(0b00000000000000000000000000000000);
/**
* 右移:-3>>2
* 在进行位运算的时候要把数据转为二进制位,并且全部都是二进制补码形式!
* 规则:符号位保留不变,数据位右移2位,高位补符号位
* -3的原码: 0b10000000000000000000000000000011
* -3的反码: 0b11111111111111111111111111111100
* -3的补码: 0b11111111111111111111111111111101
* -3>>2: 0b11111111111111111111111111111111
*/
System.out.println("-3 >> 2 = " + (-3 >> 2));
System.out.println(0b11111111111111111111111111111111);
}
}
无符号右移运算:
public class Test5 {
public static void main(String[] args) {
/**
* 无符号右移:3>>>2
* 在进行位运算的时候要把数据转为二进制位,并且全部都是二进制补码形式!
* 规则:数据位右移2位,左边空位都补0(包括符号位),负数会变成正数
* 3的原码: 0b00000000000000000000000000000011
* 3>>>2: 0b00000000000000000000000000000000
*/
System.out.println("3 >>> 2= " + (3 >>> 2));
System.out.println(0b00000000000000000000000000000000);
/**
* 无符号右移:-3>>>2
* 在进行位运算的时候要把数据转为二进制位,并且全部都是二进制补码形式!
* 规则:数据位右移2位,左边空位都补0(包括符号位),负数会变成正数
* -3的原码: 0b10000000000000000000000000000011
* -3的反码: 0b11111111111111111111111111111100
* -3的补码: 0b11111111111111111111111111111101
* -3>>>2: 0b00111111111111111111111111111111
*/
System.out.println("-3 >>> 2 = " + (-3 >>> 2));
System.out.println(0b00111111111111111111111111111111);
}
}