1:信息存储
- 0x开头是16进制
- 0b开头是二进制
1.1:十六进制表示法
十六进制使用“0-9”与“A-F”来表示16个可能的值。 不区分大小写
在Java中16进制数要有前缀0x,一样的不区分大小写
例如:十六进制的10: 0xa
十六进制数字 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
十进制值 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
二进制值 | 0000 | 0001 | 0010 | 0011 | 0100 | 0101 | 0110 | 0111 | 1000 | 1001 | 1010 | 1011 | 1100 | 1101 | 1110 | 1111 |
16进制 10进制 2进制之间的转换
(1):2进制与16进制之间的转换
十六进制转换为二进制:
一个十六位数字可以转开为一个4位二进制数,通过展开每个16位数字,就可以转换位二进制数。
例子:将0x173a4c转换为二进制数
十六进制数 | 1 | 7 | 3 | a | 4 | c |
---|---|---|---|---|---|---|
二进制数 | 0001 | 0111 | 0011 | 1010 | 0100 | 1100 |
这样就得到了二进制表示:0001 0111 0011 1010 0100 1100 |
二进制转换位16进制:
分为每4位一组的二进制数,如果总数不是4的倍数,那么左侧补0。 将每四位二进制数替换为对应的16进制数即可。(十六进制转二进制的反过程)
(2):10进制与16进制之间的转换
- 十进制转16进制
一个十进制数x,要转换为16进制数。反复地用16除x,得到一个商q和一个余数r,也就是x=16*q+r。然后我们用16进制表示地r作为最低为数字,并且通过对q反复进行这个过程得到剩下地数字。
例如:十进制数314156转换为16进制
314156=1963416+12
19634=122716+2
1227=7616+11
76=416+12
4=0*16+4
注意16进制数为0x4cb2c
- 16进制转换为10进制
用相应地16地幂乘以每个16进制数字,求和。
例如:数字0x7af转换为10进制数字
7 * 162+10 * 161+15 * 160=1967
(3):10进制与2进制的转换
-
10进制转换为2进制
用10进制数反复除以二,商继续除以二,余数作为最低位的值。 -
2进制数转换位10进制数
每一个二进制位乘以相对应的2的幂然后相加求和得到十进制数。
例如:二进制数1010转换为十进制数
1 * 23+1 * 21=8+2=10
1.2:寻址和字节顺序
对于跨越多个字节的对象
- 对象的存储:连续的字节
- 对象的地址:最小地址字节的地址
字节排序
- 大端法:低地址存最高有效字节,低地址为高位
- 小段法:低地址存最低有效字节,低地址为低位(个位)
不同机器的选择可能不同
三种情况没有理解
1.3:布尔代数
- 从boolean类型衍生到二进制的运算(也叫位向量)
运算 | 结果 | 结果 |
---|---|---|
a | 1001 | |
b | 0011 | |
~a | 0110 | 取反,但是单Java中int类型的a取反并不是0110,因为int类型32位,高位会全部变为1 |
a&b | 0001 | 各位取与操作 |
a|b | 1011 | 各位取或操作 |
a^b | 1010 | 各位取异或操作 |
使用二进制数据(位向量)表示一个集合
- 可以使用一个二进制数表示一个有限的数字集合,一个10位的二进制数据,可以表示0-9这十个数字的集合及其子集
- 二进制数据低位开始由0开始编号下标
- 当集合存在一个数字i时
- 该二进制数据下标为i的数就为1
- 反之为0
- 此时的操作:
- &:取交集
- |: 取并集
- ~:取补集
使用二进制数据进行掩码运算
-
0xff表示低八位全一的掩码
-
任何二进制数与该掩码进行或(|)运算
-
x | oxff
-
会得到一个由x最低八位有效数据组成的数据
-
~0,会得到一个全一的掩码,这个掩码有多长就看数据类型了,比如int的0,取反取掩码就是32位的1
逻辑运算
只要非零就位真。
运算符 | 含义 |
---|---|
| | | or |
&& | and |
! | not |
移位运算
在Java中
符号 | 作用 |
---|---|
<< | 左移 |
>> | 算数右移(高位补元素最高位数,全一或者全0) |
>>> | 逻辑右移(高位补0) |
2:整数表示
- java只支持有符号数,没有无符号数
2.1:无符号数编码(Java没有无符号数)
- 就是使用对应的二进制原码进行编码
2.2:补码编码(有符号数编码)
- 有符号数的编码
- 最高位为符号位,1表示负数,0表示非负(含0)
补码到整数的映射:
公式:- 符号位*2下标+后面的每一位 * 2下标
这样可以求得补码对应的整数值。
示例:
1011=-123+022+121+120=-8+2+1=-5
一个w位的补码能表示的最大整数和最小整数:
- 最小:[1000…0]
- 最大: [011…1]
- 补码的范围是不对称的,|最小|=|最大|+1
- 能表示的整数比负数少一个,非负数外加一个0
2.3:有符号数和无符号转换(Java中不涉及)-就是换一个编码方式读
- 无符号转有符号
- 高一位是0不变
- 高一位是1变为负数,公式: 无符号数-2位数
- 有符号转无符号:
- 大于等于0,意义不变
- 小于0,按照无符号的意思读就行了,公式:有符号数+2位数
有符号(4位) | 无符号(4位) |
---|---|
-8 | 8(-8+24) |
-3 | 13 |
-1 | 15 |
0 | 0 |
8 | 8 |
2.4:扩展/截断一个数字
- 截断: 大位数转换为小类型时,可能装不下,就会被截断,数据发生改变
- 截断就是按照新位数,高位都不要了,低位部分的按照意义读就行了,数据可能会发生改变
- 扩展: 小为数转换为大位数:数据不会被改变
- 无符号:高位补0
- 有符号:
- 非负数,高位补0
- 负数,高位补1
- 非常向逻辑与算数右移,但是右移过去的低位不丢失
大转小,截断
long b=0b1000000000000000000000000000000000000000000000000000000000000000l;
、--------------------------、这些高位都被截断丢弃了。
int a= (int) b;
System.out.println(a);
>>> 0
昨日问题:无符号0-1的计算
3:整数运算
3.1:无符号加法
两个W位的二进制数相加可能会溢出
两个非负整数:0<=x,y<2w
则 x+y由两种情况:
- =x+y, x+y<2w正常
- =x+y-2w, 2w<=x+y<2w+1溢出
就是按照数据类型的位数截断再读。
溢出:完整的整数结果不能存放到数据类型的字长限制中去。
如何判断一个无符号假发发生了溢出?
如果x+y的结果比x和y都小,那么可以确定一定发生了溢出。不会出现比一个大比一个小的情况。
无符号数求反
虽然只有正数但是,这里也可以求反,因为每一个数都可以找到另一个正数与之相加等于0的情况。
一个无符号数x求反得到-x
- =x ,x=0;
- =2w-x,x>0
无符号数求反还是非负数,但是不变的是,-x+x=0
3.2:补码加法(有符号数加法)
两个w位二进制数x,y相加
其中-2w-1<=x,y<=2w-1-1.
那么x+y:
- x+y-2w ,2w-1<=x+y正溢出
- x+y,-2w-1<=x,y<=2w-1-1正常
- x+y+2w, x+y<2w-1
只有两个正数相加才可能发生正溢出。两个正数相加得到了负数时正溢出
只有两个负数相加才可能发生父溢出。两个负数相加得到了非负数时负溢出
一正一负的数相加不可能发生溢出
补码的非
与我们平常的概念就很相近了,因为有与之对应的负数或者正数,x的求反就是-x,也就是对应的正数或者负数。
例外的是最小数(-2w-1)求反还是它本身。 1000+1000才等于0.