计算机中的小数

1.JAVA之父James Gosling说过:其实95%的编程者对小数一无所知。

                       

                                                   

2.没错,在学编程的很长一一段时间里,我们根本没有关心数据在计算机内部到底是怎么表示的,最多知道个什么是寄存器,知道什么是内存,什么是缓存,磁盘I/O之类的。有句话怎么说来着,只有明白原理才能利用好原理来做事情。那么我们今天就来看看小数在计算机内部到底是怎么表示的。

3.看这个问题,首先需要了解什么是寄存器(如果不知道,也没关系,就当他是个容器)。我们知道,在32位系统上,其实数据是被32个01表示的。这是底层硬件所决定的,没法改变。我们能改变的只有自己的理解方式。我们首先还是先说一下整数是怎么表示的吧。

4.整数在计算机中的表示。上边我们已经知道了,对于一个寄存器,大小是4个字节,也就是32位。但是寄存器是没有变量类型的,也就是说它是不会管你这里面存的到底是整数还是负数,到底是整数还是小数(不是它不管,是它根本也管不了)。所以寄存器中的数据类型是有操作类型决定的。比如你在使用add指令的时候,这里面就是个有符号的数据,addu这里面的数据就被理解成无符号的数据。这些我们需要了解。知道了这些之后,我们知道,一个int是4个字节,32位,那么它是怎么被存在计算机中的呢?我们暂时先从寄存器的角度来看,其实一个int寄存器中被划分成了两个部分:符号为+数字位。在这个32位数据中,第一位就是符号位,它决定了这个数到底是正数还是负数,其中符号为为0就是正数,为1就是负数。由于这32位被拿出来一个当作符号位,所以它的有效位数就成了31位,这也就是为什莫int的范围是:-pow(2,31)-1~pow(2,31)-1.OK,知道这些,我们说说今天的重点:小数的表示。

5.我们知道,小数一般被写成科学记数法的这种形式:

                                                            

这是一个十进制下的某个小数的表示,底数,指数,以及系数还有小数点。那么我们首先分析一下,计算机中底数肯定是2这个没有问题。因为计算机使用二进制。然后就是指数,指数这个没有变化,最后就是系数了,其实系数是确定的,一定是1,为什莫呢?我们知道,在十进制下的科学计算法,我们的系数(我这里指的是小数点前边的数)一定是小于10的,否则就要进位。同理,二进制下,这个数据一定是小于2的,但是又不能等于0,所以只能是1.我们就可以把二进制下的科学计算法写成这种形式:

                                

由于小数点前边的数据一定是1,所以我们可以不储存这个数据。那么我么继续思考,上面我们说了,寄存器是32位,他不会管你到底是什么数据,其实真正不同的是我们怎么去理解这32位。那么整数是上面那样理解的,小数又该怎莫办。我们用float为例子来解释这个问题。其实,小数在理解的过程中,32为数据是被这样划分:

                          

32位数据被划分位三个部分,符号为,指数位,数字位。计算的时候和一般的计算方法相同,但是别忘了加上我们没有储存的1.有人可能会问,为什莫指数是E-127.这是IEEE 754的标准,称作指数偏移法的表示。

6.虽然我们一定程度上解决了小数的储存和表示的问题,但是我们在编程中经常会遇到程序中出现什么nan之类的东西,nan其实就是not a number。他们这些异常的数据在计算机中的存储是怎么样的?

在IEEE 754中,有这样的一些规定,其实这些东西的表示也是基于表示小数的启发,有这样一张表格:

                                                      

我来解释一下这个表格:还是我们刚才的那个公式:我主要解释一下第二行和最后一行:我们知道,任何数据类型都是有精度的,对于小数这种类型,不仅仅有上界,也有下界,这个下界不是说负的,而是它到底可以表示到小数点多少位。一旦超出这个精度,其实数据就不准确了。这也就是我们常说的丢精度。其中如果指数是0,数字位非0,那么就代表这不是正常的数据,也就是说丢了精度。最后一行就是我们说的,不是一个数字。NAN

这大概就是小数的一些细节东西,有待补充。  

猜你喜欢

转载自blog.csdn.net/weixin_41863129/article/details/85630261