1) 十进制
逢10进1
基数: 10
权: 10^n, 10000 1000 100 10 1
23678(10) = 2*10000+3*1000+6*100+7*10+8*1
= 2*10^4 + 3*10^3 + 6*10^2 + 7*10^1 + 8*10^0
= 23679
2) 二进制
逢2进1
基数: 2
权: 2^n, 128 64 32 16 8 4 2 1
01000001(2) = 1*64 + 1*1
= 65(10)
3) 补码基础
-128 10000000 11111111 11111111 11111111 10000000
10 2进制 ... ...
8421 11110111 11111111 11111111 11111111 11110111
-8 1000 11111000 11111111 11111111 11111111 11111000
-7 1001 11111001 11111111 11111111 11111111 11111001
-6 1010 11111010 11111111 11111111 11111111 11111010
-5 1011 11111011 11111111 11111111 11111111 11111011
-4 1100 11111100 11111111 11111111 11111111 11111100
-3 1101 11111101 11111111 11111111 11111111 11111101
-2 1110 11111110 11111111 11111111 11111111 11111110
-1 1111 11111111 11111111 11111111 11111111 11111111
0 0000 00000000 00000000 00000000 00000000 00000000
1 0001 00000001 00000000 00000000 00000000 00000001
2 0010 00000010 00000000 00000000 00000000 00000010
3 0011 00000011 00000000 00000000 00000000 00000011
4 0100 00000100 00000000 00000000 00000000 00000100
5 0101 00000101 00000000 00000000 00000000 00000101
6 0110 00000110 00000000 00000000 00000000 00000110
7 0111 00000111 00000000 00000000 00000000 00000111
00001000 00000000 00000000 00000000 00001000
.... ...
127 01111111 00000000 00000000 00000000 01111111
补码运算:-1 1111
-1 1111
*
----------
1111
1111
1111
1111
101010
-----------
0001
4) A Java 内部只有二进制补码
B Java 内部采用补码运算, 自动发送上溢出和下溢出
C Java内部没有10进制! 但是Java尽量按照人类习惯输入输出
D 补码的负数 最高位是 1, 也称作符号位
5) 16进制, 是2进制的简写, 方便专业人员书写2进制数据
16进制
逢16进1
基数: 16
权: 16^n, 256 16 1
16进制数字: 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
41(16) = 4*16 + 1*1
= 65(10)
= 0100 0001(2)
8421 8421
4 1 (16)
128 64 32 16 8 4 2 1
0 1 0 0 0 0 0 1
练习:转换以下十进制为二进制 192(10) 137(10) 145(10)
192(10) = 1100 0000 (2)
c 0 (16)
-8(10) = fffffff8(16)
需要补充说明的是,用四位的二进制表示数据,最多能表示0-15(10进制),之后又牛人做了一个细微改动,
将所有二进制以1开头的数(大于2的(4-1)次幂的数(理论上的最大数))放到0之前,并且规定用来表示
负数-1到-8,这就是4位补码,如下;
-8 1000 =8
-7 1001 =9
-6 1010 =10
-5 1011 =11
-4 1100 =12
-3 1101 =13
-2 1110 =14
-1 1111 =15
0 0000
1 0001
2 0010
3 0011
4 0100
5 0101
6 0110
7 0111
仔细观察会发现,-1(1111)+1(0001)=0(1 0000),如果溢出最高位"1",仅保留4个"0"(因为仅为4位运算)
,那么得到-1+1=0,同理-8(1000)+7(0111)=-1(1111).
至此,我们得出结论:
在封闭的四位运算中,(超出四位就丢弃),这种设计和规定是非常合理的
另外,-1(1111)*-1(1111)=1(0001)也是成立的,而这种数据运算规矩就是补码运算
知识点:
计算机中正数和负数的关系是取反加一。举例如:~3+1=-3(~3表示对3取反)
补码运算时封闭的:运算结果保留在补码范围之内,超范围就溢出
补码边界运算有溢出风险
4位二进制补码最多能表示 2^4 个数,-2^( 4-1)~2^( 4-1)-1
8位二进制补码最多能表示 2^8 个数,-2^( 8-1)~2^( 8-1)-1
16位二进制补码最多能表示 2^16个数,-2^(16-1)~2^(16-1)-1
32位二进制补码最多能表示 2^32个数,-2^(32-1)~2^(32-1)-1
如下,有一个笔试题
现有2个byte类型的变量a=126、b=5,当执行a=(byte)(bb1+bb2);语句之后,a的值应该是( )。
A、-128 B、131 C、-125 D、语句在编泽中出错
答案:C
首先,a=a+b=131已经越界啦,那么在java中默认的类型是int,但是前面有强制类型转换为byte,
所以编译通过。而131=1000 0011,取反加一得其负数 0111 1101=125,所以(byte)131=-125
另外,我们需要论证一下,byte类型的八位的补码最多能表示2^8个数,
为-2^( 8-1)~2^( 8-1)-1其实如果将补码后的负数都算成正数的话,
既表示的数值范围为0~(2^8)-1,也就是0~255,而如果超出这个范围 ,比如说
求出(byte)256的值,很显然256为16位 既 0000 0001 0000 0000 对其取反加一得负数
1111 1110 1111 1111 + 1 =1111 1111 0000 0000而byte为八位,所以越界部分丢弃得0000 0000
所以得(byte)256=0,
那么我们再求(byte)(256+1)的值呢?
同上257=0000 0001 0000 0001对其取反加一得负数
1111 1110 1111 1110+1=1111 1111 1111 1111,丢弃越界部分得1111 1111 很明显结果为-1
所以得(byte)(256+1)=-(-1)=1
继续发掘
求(byte)(256-1)
同上255=1111 1111 取反加一得负数
0000 0000 + 1=0000 0001 =1
所以得(byte)(256-1)=-1
所以综合得出如下公式:
(byte)((2^8)*m +/- n)= (+/-) n {(2^8)*m +/- n的范围-2^( 8-1)~2^( 8-1)-1}