《程序是怎么跑起来的》读书笔记(3) -- 万能的计算机为什么就是算不对0.1+0.1

这一章比较前两章,很容易懂,而且很有意思。

其实我原来学java的时候,老师就说过关于单精度和双精度的问题,但是可能当时老师没讲清楚或者还是当时水平太烂,根本没想过这种事情,为什么计算机遇到小数就跟你提精度。


不过我亲身尝试,我问了两个实验室的人这个问题,他们理解的也不是很深刻,一下子让我觉得这本书真的是好明白你学习过程中的漏洞在哪里,切入正题。

0.1连加100次,最后的结果可能是10.000002
接着上会的说,你可能知道01010011这种二进制去表达一个整数,但是二进制表达小数是怎么做的?
1011.0011 小数点后面就要开始*2(-1)次幂,然后它只能出现0.0和0.5对吧,两位可以有0.00,0.25,0.5,0.75,位数越来越多,能表达的数越来越多,但是在有限位数的情况下有些数永远不可能被等于,比如0.1,你现在应该明白为什么会出错了吧

在结合实际一点,很多编程语言提供了两种表示小数的数据类型,比如双精度浮点数和单精度浮点数
双是64位,单是32位,按刚才说的0.1永远你不能用有限个2的n次幂各种组合相加得到,位数越高肯定精度越高

浮点数=符号(尾数*基数的指数次幂)
二进制基数就是2,没毛病
浮点数符号占一位,其他给指数和尾数
双精度64=1符号+11指数+52尾数
单精度32=1符号+8指数+23尾数

尾数使用的是小数点前面的值固定为1的正则表达式,指数使用的是EXCESS系统
原来一直想当然的以为正则表达式只是字符串处理的。其真正定义是按照特定的规则来表示数据的形式。

比如单精度的11.0175这个数如何变成二进制
对于尾数,首先小数点前面值固定为1,
11.0125 == 1011.001 右移 0001.011001 补全单精度的23位 最后得到01100100000000000000000;

然后是指数,指数有8位吧,那就是8位最大表示255对,其255和0的中位数127,然后00000001就代表1-127=-126,指数就是-126次幂
以0.75为例
0.75按字节的每一位打印就是0-01111110-100000000000000000000000
0代表正,01111110等于126,126-127=-1 就是-1次幂
100000000000000000000000其实是1.100000000000000000000000=1.5
1.5*2(-1)=0.75

后面是一些零零碎碎的东西,比如想要准确怎么办——BCD,16进制用0x开头代表

下一次,应该就是内存了,这个是我最想看的一章。

发表评论

电子邮件地址不会被公开。