可能有的小伙伴不理解了:为啥这节讲这些呢,不应该先把语法什么的学习一下吗?
在之前的文章里面讲过,C语言的学习是需要了解一点计算机工作原理的。可能在初学时期用不到,但是如果真的要深入研究的话,是绝对避免不了的。况且这节的内容其实比较简单,我们不如先把它了解了,方便日后我们的进阶学习。
学习编程,尤其是底层编程,进制转换是一个避免不了的话题。其实我们仔细去观察,发现其实是有不少规律可循的。
进制转换
-
二进制 -> 十进制
这个方法就四个字:
按权相加
数学公式来表示就是:
我们先来了解下位权的概念,举个栗子你就明白啦:
二进制数 00101011 对应位权 76543210 于是就有了方法:
十进制 = 依次将每个二进制位的值乘以2的位权次方再相加
另外说明一下:按权相加适用于任何进制的数到十进制的数的转换哟!
-
二进制(补码) -> 十进制
如果符号位为0,那就和上面一种情况一样。
如果符号位为1,则此时符号位的位权不变,但该位的权值应该乘以**-1**,如:
大家可能看懵了,啥是符号位?补码又是啥?别急,后面且听我娓娓道来。
-
十进制 -> 二进制
这好像大家高中的时候学过吧,这里我总结下:
将待转换的十进制数不断地除以2,直到商为零,然后将每次除得的余数倒序拼凑即可。
-
二进制 <-> 八进制
这个很简单,只需要把数字从0位权开始三个一组分开,然后分别转化成八进制数再拼接起来即可。这里提供个表格,方便不想转换的同学查表。
二进制 八进制 000 0 001 1 010 2 011 3 100 4 101 5 110 6 111 7 -
二进制 <-> 十六进制
这个就更简单了,只需要记住如下的表格,然后将二进制数从0位权开始四个一组分开,分别对应后再重新拼凑即可。
二进制 十六进制 0000 0 0001 1 0010 2 0011 3 0100 4 0101 5 0110 6 0111 7 1000 8 1001 9 1010 A 1011 B 1100 C 1101 D 1110 E 1111 F
原码
在了解这些码之前呢,我们先来了解一下基本知识。
首先,我们要知道,计算机中,存放一个数据最小的单位是bit(位,也称比特),而在TCP/IP协议中,规定1Byte = 8bit
,Byte(字节)是最小的容量单位。因此,一个字节里面就有8个位。那么如果使用一个字节来表示数字的话,就是个数。那么为了表示数字的符号,我们又规定,一个字节中的最高位(也就是最左边的那一位)是符号位,符号位为0表示的是非负数(记住,是正数和0),1则表示的是负数。
原码,实际上就是将十进制数转化成二进制的形式,然后把符号位加上即可。比如说5的原码,先转化为二进制,即101
,再填充至7位,即000 0101
,然后因为是非负数,符号位为0
,那么5的原码就是0000 0101
。
明白了吧,是不是觉得特别简单呢?那么-5的原码又是啥呢?
聪明的你一定想到了,就直接把符号位变为1
就行啦,即1000 0101
。
简直完美啊,如此简洁地表达了数字在存储器中的表示方式。直观形象又好记!
But!现在该说但是了。请问5和-5相加等于多少呢?
0啊!当然是0!这难道还要思考吗??
是的,没错,但是你用两个数的原码加起来看看等于几?
咦?咋就不等于0了呢……
没错,问题就在这。如果用这种所谓的直观的形式去表达,既有悖于我们的常识,又不方便计算机的电路设计,于是我们的先人们开始了探索。
反码
我们从上面的例子了解到,负数在表达的时候,不能这么图方便,不然可能会造成一些冲突和错误。先人们就开始折腾。结果弄出来反码这个东西。
我们说了,只是负数的表达除了问题,所以正数无论是原码,反码还是后面我们讲的补码,都是不变的。要变的只有负数。
负数原码转反码的方法很简单,符号位单独不变,只需要把其他的按位取反即可。什么叫按位取反呢,说成人话,就是0变1,1变0。还是拿刚刚的-5作为栗子。-5的原码为
1000 0101
那么转化为反码,符号位不变,其余按位取反:
1111 1010
懂了吧,那么这样5和-5相加会得到什么呢?
我们发现,得到了一个8bit能表示的最大的值。这个路子能否成功,就看临门一脚了。距离成功仅一步之遥。
补码
这个“临门一脚”就交给补码啦。补码的出现,相反数相加不为0的情况才被彻底解决。那么补码又是个啥东东呢?
正数的补码还是原码,这个刚刚说过了。而负数的补码,则是在反码的基础上加个1。可为啥是1呢?上面那个反码的例子,我相信大家是有些想法了,如果给1111 1111
这个数加个1,那么等于多少呢?
答案是1 0000 0000
。
又的小伙伴可能会抬杠了,那还是不等于0呀。我们注意观察,这个数已经达到9位了,最高位已经溢出一个Byte,那么对于一个Byte所表示的数字,计算机可以将最高位直接舍弃,bingo!不就变成0000 0000
了吗?
是不是很奇妙呢?不得不说,先人们着实厉害呀,在这里向他们致敬!
另外,还要提醒一点,就是补码的补码就是原码,至于为什么大家可以回去自己试试,这里就不多赘述咯('')
最后,在这篇文章结束前,我还想提醒一句:**正数是三码归一!!**别到时候别人给你一个正数叫你转换,你还按位取反啥啥啥的,那样就丢人啦!
今天的博客就到此结束啦,如果你喜欢笔者的文章,记得点个赞哦(≧∇≦)ノ