大家先思考一下,这里有一堆8位的二进制数:
00000000 10000000
00000001 11111111
00000010 11111110
01111111 10000001
在电脑中数值都是像这样的二进制表示出来的。如果都是正数这八个数是
0,128
1,255
2,254
127,129
可以直接计算得到,那如果有负数怎么办呢?
直接规定:用数据的最高位表示正负,0表示正,1表示负。这就是原码
有人可能就进入一个思想误区:既然把数值的一个位占用成了符号位,那表示的数就减少了,减少了一个位,本来能表示28个数,现在只能表示27个了!
没错只能表示27个数,但是因为符号位表正负了,所以要把27*2=28
有人又可能发现问题了+127 ~ -127 只有255个数,那 0 岂不是有了正负,当然不可能有-0。可以看出来,这种表示有符号位的方法是有问题的,它并不能正确的表示有符号数。
反码同理。0出现重码
为了解决这种问题,补码就出现了,先确定用00000000b ~ 01111111b表示 0 ~ 127,然后再用它们按位取反加1后的数据表示负数。
正补十进制 | 正数补码 | 负数补码 | 负补十进制 |
---|---|---|---|
0 | 00000000b | 10000000b | -128 |
1 | 00000001b | 11111111b | -1 |
2 | 00000010b | 11111110b | -2 |
127 | 01111111b | 10000001b | -127 |
给出一下二进制小数:
0.0000 1.0000
0.0001 1.1111
0.0010 1.1110
0.1111 1.0001
二进制的小数是一个神奇的东西,一定要注意。我们顺便复习一下小数的二进制转换十进制:
如:
0.0001=0*2-1+0*2-2+0*2-3+1*2-4=0.0625
0.0010=0*2-1+0*2-2+1*2-3=0.125
观点和整数补码一样,直接上表,就很直观
正小补十进制 | 正小数补码 | 负小数补码 | 负小补十进制 |
---|---|---|---|
0 | 0.0000 | 1.0000 | 1 |
0.0625 | 0.0001 | 1.1111 | -0.0625 |
0.125 | 0.0010 | 1.1110 | -0.125 |
0.5 | 0.1000 | 1.1000 | -0.5 |
0.9375 | 0.1111 | 1.0001 | -0.9375 |
在计算机中 纯整数 和 纯小数 用定点整数和定点小数表示,既有小数又有整数的数就用浮点数表示。
纯整数:127 或10000001b
纯小数:0.125 或 1.1110b
浮点数:127.125 既 01111111.0010
浮点数通常可以用来表示任意一个实数。
浮点数 = 尾数 * 基数阶码N = M * r E
(其中尾数是一个规格化的纯小数)1
看到这个表达方式大家应该很熟悉(哦,不!应该是熟悉的陌生感),仔细看一下这不就是科学计数法吗?基数是2时就成为电脑可以存储的浮点数了。
举个例子:
二进制:11100.101 = 0.11100101 * 10101
写成十进制:28.625 = 0.89453125 * 25
我发现写成混合模式容易发现其中的奥秘: 11100.101 = 0.11100101 * 25
在对比一下小学二年级学的科学计数法:234.12 = 2.3412 * 102
电脑中肯定不能这么存了,那电脑中怎么存浮点数呢?
一般浮点数在机器中的存放格式为:
数符 | 阶符 | 阶码 | 尾数 |
---|
或
阶符 | 阶码 | 数符 | 尾数 |
---|
值得注意的是当尾数= -1/2 时,对于原码来说是规格化数,对于补码不是规格化数。 ↩︎