C++与C#对比学习:数字的故事

来源:互联网 发布:虎嗅招聘php 编辑:程序博客网 时间:2024/06/08 11:51

 进制的故事

 

       跟数字打交道时我们接触的最多的是十进制了,我们从小学到大学的数学课基本上都用的十进制.但实际上还存在各种各样的其他进制.比如时间就是60进制,中国古代用十六进制表示重量,十六两是一斤,所以有成语半斤八两.

      而我们现在普遍使用的电脑跟二进制是离不开,可以说如果没有二进制的发明就没有计算机如今的普及,这就得感谢莱布尼兹这样的牛人了啊,其实计算机领域真正的牛人基本上是搞数学的.毕竟计算机的理论基础就是数学嘛.通过二进制这么简单的东东能演化出电脑这么复杂的功能,真的让人觉得这个世界真神奇啊.简单就是美,这是很多科学家的座右铭.很多伟大 的理论就只是一个简单的数学式子,比如牛顿力学三大定律,爱因斯坦质能方程.人的基因其实组合也很简单,就是一对对的碱基对,但最终组合出来的结果复杂的吓人啊.

 

二进制不一定是最好的  

      二进制理论上是非常完美的,当其实实现起来还是不太好,随便表示个啥东东都要那么多晶体管组合出来.但由于现在技术的限制,晶体管只能通过开关两种稳定的状态来表示0,1两个数字.假如晶体管能够表示8种状态那多爽啊,这样以前要用八个晶体管表示一个字节,现在只要一个就搞定,成本降低了八倍.这样的话二进制就再没任何用处,直接用八进制就行.如果一个晶体管能表示10个状态,那更完美.直接套用我们习惯的十进制,不用再用烦人的二进制.可惜理想是美好的,现实是残酷的.暂时没法做到那样.不过有很多人现在在研究量子计算机,一个量子可以表示很多种状态.具体多少不知道,反正肯定大于2.另外除了能表示多种状态外,还有些其他的特性,可以给计算机带来更强大的功能.不过现在只是研究阶段,要真正实现并推向市场不知道哪年哪月去了.

 

为啥用八进制和十六进制

     在计算机里用二进制我们比较容易理解,那为啥还有八进制,十六进制呢? 其实只是为了表示方便,我们看起来顺眼,交流方便.一连串的01谁都看的晕啊.反正不管你搞多少进制,计算机最后识别的就二进制.那有人说为啥不直接用十进制得了啊,为啥整个怪怪的八,十六出来啊.我觉得用十进制是完全可以的.不过我觉得八进制,十六进制也有些优势.比如转换起来比较方便.我们知道十进制转行成二进制要用啥辗转相除法,如果位数比较多就较麻烦.而八进制的话,只要把每一位替换成对应的三位二进制,然后顺序不变,就OK了.十六进制就是每一位替换成对应的四位二进制.反过来的话二进制转八进制就是从右向左每三个一组,左边最后一组不足三就补0,然后每一组转换成八进制数就行.二进制转十六进制就也一样,只不过四个一组.另外十六进制的话表示的数字会比十进制更短.所以我们平时用十六进制较多点,八进制现在用的少了.

在C++中表示八进制的字面值是前面加个0(数字0),十六进制是0x(数字零和字母x).例如 int eight = 011;   //十进制9                  int sixteen = ox10;//十进制16

在C#中就没有八进制的字面值表示了int eight = 011;//十进制就是11而不是9;           十六进制是跟C++一样

微软的官方文档里是这样说的,只有十进制和十六进制的字面表示了

Integer literals are used to write values of types int, uint, long, and ulong. Integer literals havetwo possible forms:decimal and hexadecimal.

 

正负数二进制表示

    我们知道怎么把十进制数转化成二进制数,但具体在计算机中怎么表示呢? 这里要说下程序运行时内存中表示硬盘实际保存时的区别.硬盘保存啥文件,基本上全是当字符处理,每一个数字对应的是字符数字,现在流行unicode,就把每个字符用unicode中对应的数字表示.最后这些数字全转化成01串.如果里面的内容代表其他啥特殊意义都是应用程序读取后作另外的处理了.

像我们表示数据类型时用啥int,long之类的说的是在内存中的表示.举个简单的例子吧.用一个字节的类型举例,C++中的char,C#中的byte.

假如unsigned char ch = 128; //由于是无符号的数字,不用关心正负号,用八个01串全部表示数字.于是在内存中就是10000000.也就是1后面7个0.

补码表示负数

    但如果有符号时咋整啊.就用8位中的第一位表示符号,0表示正数,1表示负数.剩下的7位表示具体数字.这样char类型只能表示-128至127这个范围内的数字了.那根据这种转换规则前面的数字10000000表示多少呢?第一位是1表示负数,后面全0那自然是0,于是这数是-0? 其实这个不一定,要看CPU的指令集怎么设计,有些计算机可能确实这么处理,这么表示.不过大部分不是这样.大部分计算机表示负数时不这样直接表示,而是把负数转换成它对应的补码.这样的好处是以后不用再管负数和减法了,只要考虑加法就行,两数相减就是一个数加一个负数.

补码的转换是这样的,先把负数的绝对值所有位取反,然后加1.

举个例子,-128.它的绝对值是128,128是10000000(这里不用考虑符号的事).再取反就是01111111,然后再加1就是10000000(怎么变回去了啊,-128,跟128一样了啊.这只是巧合,127和-127就不一样的.于是-128在内存中表示和128一样都是10000000.不过应用程序读取出来肯定不会当成一样的.应用程序还有这个数字的其他信息,如果知道它是无符号数就当成128,如果是有符号数就是-128

所以在内存中两个一样的值,被你读出来时看你当成什么类型,不同的类型就被转换成不一样的结果.有时结果一样,有时不一样.

你可以验证下,unsigned char num = 128;   char ch = (char)num;      //ch是-128.而不是期望的128.所以我们一般会说某种类型只能表示某个范围内的数字,超出了就是值溢出,会得到个错误的结果.

 

整数的表示比较简单点,浮点数的表示就非常复杂了.这里先不讨论.