计算机内数据储存方式及数据溢出原理
1 原码
原码即计算机的二进制码,特点:
-
在计算机数据储存中最高位为符号位,正数为0,负数为1
-
除开最高位,剩余位数代表这个数的绝对值大小
-
附属的原码是在其数值绝对值基础上再将最高位变为1
例子(原码):
| 数字 | 原码 |
|---|---|
| +22 | 0001 0110 |
| -22 | 1001 0110 |
| +33 | 0010 0001 |
| -33 | 1010 0001 |
原码的表示简单方便,但是在使用过程中,进行运算时,必须比较二者绝对值大小,才能确定计算结果的正负。所以原码不便于使用。所以一般用补码来进行运算。
2 反码
反码没有赋予功能进行实际使用,他的作用主要是用来过渡补码,作为补码和原码的桥梁。具有以下特点:
- 对于正数的原码转换为补码,其二进制码不变。
- 对于负数变为补码,符号位不变(即最高位的1不变),剩余位数变为其相反的数(1变为0,0变为1)
例子(原码和补码转换):
| 数字 | 原码 | 补码 |
|---|---|---|
| +22 | 0001 0110 | 0001 0110 |
| -22 | 1001 0110 | 1110 1001 |
| +33 | 0010 0001 | 0010 0001 |
| -33 | 1010 0001 | 1101 1110 |
3 补码
补码,才是计算机中用来储存数值的正统血脉。为了方便计算计算机的数值一律使用补码储存。具有以下特点:
- 在正数中补码与原码和反码相同。
- 负数中补码符号位不动其他位变为其相反的数,再加1即得到原码。
- 负数中补码是由其反码+1得到
例子(原码-反码-补码):
| 数字 | 原码 | 反码 | 补码 |
|---|---|---|---|
| +22 | 0001 0110 | 0001 0110 | 0001 0110 |
| -22 | 1001 0110 | 1110 1001 | 1110 1010 |
| +33 | 0010 0001 | 0010 0001 | 0010 0001 |
| -33 | 1010 0001 | 1101 1110 | 1101 1111 |
4 补码的意义
我们知道0是一个特殊的数字,根据上述三个方式我们可以得到0的两种标答方式即0000 0000来表示(+0)和1000 0000(-0)表示
那么两种方式不同意怎么办?
这时候就凸现出补码的作用了。(-0) 的反码为1111 1111,那么它的补码为1 0000 0000(这时首位的1会被舍去)即若最高位符号位进一那么那个1就会被舍去。
这时(-0)=(+0)=0000 0000。统一了0的编码格式。
那么如果只是统一0的编码格式也没必要制定如此麻烦的规。这时就不得不提到上文所说的数据的运算困难了。对!没错,它对我们计算机的加减运算也大有作用。
不过我们需要记住,在计算机运算加减法中所有的减法也视为加法去计算,如16-6=16+(-8)
我们来看一个例子:
- 22+33=55 在计算机运算中是这样的 0001 0110 + 0010 0001=0011 0111 我们转化一下$$11+12+14+116+1*32=55$$正好符合问哦们的运算结果。
- 33-22=33+(-22)=11 在计算机中是这样运算的 0010 0001 + 1110 1010 = 1 0000 1011(这里最高位即符号位进1所以我们直接抹去最高位的1)得到的结果为0000 1011由于符号位为正所以直接转化二进制,得到的数确实为$$18+12+1*1=11$$即为我们所得结果。
- 22-33=22+(-33)=-11在计算机中是这样运算的 0001 0110 + 1101 1111 = 1111 0101 (结果怎么不对啊!!!(慌张~))这里我们得到的运算结果的符号位为负数,那么我们就要将它转化为原码,先将除了符号位的其他位取反即1000 1010然后我们再加1即 1000 1010+1=1000 1011,我们将他转化为十进制看看:$$11+12+1*8=11$$那么它的大小为11,由于符号位为1,所以他的值为-11.结果正确。
5 数据溢出
看了以上文段,那我们就可以来探究数据溢出是怎么回事了。
首先我们看只有1个字节的情况(char类型),即只有8位。我们知道最高位为符号位,所以8个1/0中能表示数值大小的只有7位,所以最大为0111 1111得到的数值为$$2^7-1$$
即+127,那么如果我们再给它+1会怎么样呢?
即0111 1111 + 0000 0001 = 1000 0000
结果如上,这时候你肯定有疑问了。(什么?!这不是(-0)吗。),但是我们运行一下编译器看看结果如何。如图:
我们运行一下得到结果为
(诶!为什么是这个结果),这里我们就需要知道,符号位为1其他位为0时即为最小值$$-2^7$$
并且我们又可以发现一个事,这里我们直接从最大值变道了最小值,形成了一个闭环。所以我们可以得出char类型的取值范围为(-128)—(127)
那么我们用sizeof找一下其他类型的空间:
输出结果为
-
所以short有2位即16位二进制,最大值为$$2^{15}-1$$最小值为$$-2^{15}$$
-
int 和long 类型有4位即32位二进制,最大值为$$2^{31}-1$$最小值为$$-2^{31}$$
-
long long 有8位,即64位二进制,最大值为$$2^{63}-1$$最小值为$$-2^{64}$$
所以问哦们在不同情况下使用不同的类型,可以最大化利用电脑资源,使其不备浪费。
资料参考
b站的黑马程序员









