0.010乘以1等于0为什么29个2等于多少


你对这个回答的评价是

你对这個回答的评价是?

整数构成一个有“1”的环1是单位元,0是零元1a=a1=a是单位元的定义,0a=a0=0是环的定义的直接推论所以如果你只用环的性质的话那么可以从0a=a0=0得到1乘0等于0,如果你考虑到整数环是┅个有“1”的交换环的话那也可以从1a=a1=a推出1乘0等于0

背景应该就是这些了这本来就不是一个非此即彼的问题,硬要争是从哪个推出来那只能說两个都可以

打开chrome控制台给一个特别简单的輸入如下:

不知道你有没有吃惊,这么简单的一个计算无论在js中还是在python中,都不是准确的0.3这是为什么呢?

要了解这个问题首先我们需要知道浮点数在计算机中到底是如何进行存储的?不知道你是怎么想的总之我开始的第一反应就是假设是32位的存储空间,我可能会按照整数的存储方式去想象比如1-24位是整数位,剩余的8位代表小数这样可以吗?当然是可以的但是先考虑下下面的这个问题:

想象红色區域是所能放置的数字的最大空间,现在有个问题当我们想继续加0的时候,发现放不下了因为空间是有限的,这个时候我们会怎么辦?

对没错,科学计数法就是我们在学习过程中,如果位数太多我们一般都会用科学计数法来表示,这样的好处是书写的位数小,表示的位数多所以,回到计算机中32位来表示实数的话,最多能表示多少位2^32次方个,大约就是40亿40亿数字很多吗?多但是和无限哆的实数集来比,沧海一粟不够看的,所以计算机的设计者就要考虑这个问题了如何让计算放下更多的数字?

还记得上面说的1-24表示整数位,剩余的表示小数位吗这种存储方式就叫定点数,1-24位每4位表示一个0~9的数字的话可以有6位表示整数部分,剩余2位表示小数部分這样我们可以用32位表示从0到这样1亿个实数,这种用2进制来表示10进制的方式叫做BCD编码(Binary-Coded Decimal),比如说8421码从左往右的权依次是8,42,1等等,有兴趣的可以去了解一下

“定点数”存在哪些问题

定点数有几个明显的缺点:

  • 占了很大的位数,但是能表示的数字范围却是有限的;

  • 無法同时表示很大的数字和很小的数字

其实究其根本原因还是这种方式的“有限”限制了它,那么有没有一种方式可以让32位所能表示嘚数字,更“无限”一点更适合我们的诉求?

当然设计计算机的前辈智慧是无限的~

就像使用科学计数法一样,计算机前辈在浮点数的設计中也用了一样的思想IEEE的标准定义了2个基本的浮点数格式,一个是32位的单精度浮点数一个是64位的双精度浮点数,也就是float或float32和double或float64这两個数据格式双精度和单精度的表示形式是差不多的,我们以单精度的作为了解和学习

  1. 第一部分是符号位,用s表示代表正负,要记住嘚是在浮点数的范围内所有数字都是有符号的;

  2. 第二部分是指数位,用e表示代表指数,用8位bit表示的数字范围是0~255为了同时表示大数和尛数,我们把0~255去掉头尾(0255后面会用到)的1~254去映射到-126~127,这样同时可以表示最大最小数字;

  3. 第三部分是有效数位用f表示,代表的是有效的數位;

综合上述表示和科学计数法我们的浮点数就可以表示为公式

看完公式有没有发现问题?你会发现我们这个公式无法表示0,的确这是一个巧妙的设计,我们用0(8个bit都为0)和255(8个bit都为1)来表示一些特殊的数值可以认为他们2个是特殊的flag位,比如当e和f都为0的时候我們就认为这个浮点数是0,看下表:

以0.5为例0.5的符号位s是0,f也是0e是-1,

用32位bit表示就是

s e f 0 00 ...0 1位 8位 23位 0.5 通过这样的表示方式可以明显的发现32位所能表礻的实数范围是很大的,又因为这种方式创建的实数中小数点的位置是可以”浮动“的所以也被叫做浮点数,

到这里我们知道了浮点数昰怎么存储的了但是还没解决我们开始的问题,为何0.1+0.2!=0.3首先我们要知道0.1是怎么存储的:

可以看出来这里0.1是算不出来一个准确数字的,从0.1箌0.9只有0.5是可以求出一个准确的值的剩下的都算不出来一个准确的值,这也就是为什么0.1+0.2会导致的精度问题也就是说浮点数无论是表示还昰计算其实都是近似计算,而近似计算就一定会导致一些问题比如,你希望银行给你存钱以及算利息的时候用浮点数计算吗当然不希朢,否则你的钱算多了还好算少了岂不是亏大了~

浮点数&二进制

把一个二进制表示的浮点数(0.1001),转为10进制表示因为小数点后的每一位嘟表示的是2的-N次方,因此转为10进制就是:

可以理解为对于二进制转十进制来说,从小数点开始往左就是把2的指数从0开始过一位+1,包括0往右就是从-1开始依次-1。

把一个10进制的浮点数转为二进制的话,和整数的二进制表示采用“除以 2然后看余数”的方式相比,小数部分轉换是用一个相似的反方向操作就是0乘以1等于0为什么2,然后看是否大于1如果大于1就记下1并把结果减去1,一直重复操作

比如,十进制嘚9.1小数部分0.1转为2进制的过程为:

这是得到一个无限循环的部分”0011“,整数部分9转为二进制就是1001因此结果就是11...

把小数点做移3位,得到一個浮点数的结果是 1.... * 2 ^ 3

s = 0 f = (到23位后自动舍弃因为最长只能放23位有效数字)

指数位是3,我们e的范围是1-254 对半分正数和负数所以127表示0,从127开始加3得到結果是130,130转为二进制表示结果就是: 所以得到e=, 结果如下:

所以最终的二进制表示结果是: 01 01

如果我们再把这个浮点数表示换算成十进制, 實际得到的准确值是 9.相信你现在应该不会感觉奇怪了。

首先我们了解一下浮点数的加法计算过程是怎么样的,拿0.5 + 0.125来做计算首先0.5套用公式计算结果是:

然后,计算口诀是 指数位先对齐(小转大这里要把e统一为-1), 然后按位相加符号位和有效位e保持统一后的结果,因此:

ps: 为啥是1.25虽然我们计算得出的是1.01 但是不要忘记计算是通过2进制算的,计算十进制的时候要转回来哦所以0100000.... 后面都是0不用管,小数部分從头开始0乘以1等于0为什么2的-N次别忘了,所以结果就是2^-2 = 0.25 加上整数位的1 就是1.25了~

可以发现其实浮点数的计算过程,通过一个加法器也是可以实現的电路成本同样不会很高,但是需要注意一些别的问题:

计算过程中需要先对齐,但是有效数位的长度是23位假如有一个很大的数芓和一个很小的数字进行相加,然后对齐的过程中小数被0部位过程中直接溢出了,23位不够用了就会出现问题,补完后一些有效位被丢掉了从而导致结果上的误差,两个数的指数位差超过23比如到2^24位(差不多1600万倍),这2个数相加后结果就直接是较大数,较小数完全被抛弃叻。

有些同学会急急忙忙去chrome的控制输入下面的代码:

骗人,结果不是还有0.1吗别急,小伙伴js内置的Number是64位的,你可以试试

是不是小数沒了【这种现象也叫大数吃小数】

所以如果银行采用IEEE-754 32位的浮点数计数方法来保管存款的话,假设你是一个大老板你的账户中有2000万rmb,这個时候你的某一个员工给你打了1块钱哈哈对不起,银行给算丢了你的存款是不变的!所以,一般银行啊电商一类的都会在涉及到钱嘚时候使用定点数或者整数来计算,避免出现精度丢失的问题如果你去银行涉及数据库,一定要小心谨慎~

这篇文章我们从浮点数的表示開始到存储,到转换以及计算过程分析了真实的计算机世界中浮点数到底是怎么运行的从中也了解了浮点数究竟为何会丢失精度:

  1. 浮點数在存储的时候可能出现不能准确转化为对应2进制的情况

  2. 在计算过程中,又存在大数吃小数的可能也会导致数据不准确

精度丢失不是沒法解决的,有成熟的方案不做过多介绍,有兴趣大家可以去研究:

文章内容大部分参考自 徐文浩 老师的 「深入浅出计算机组成原理」專栏加了一些自己的理解做了一个简单的总结,之后还会继续不定时的分享一些自己的所得如果觉得还不错,点个赞吧~

ps: 有同学可能會问既然只有0.5可以转为一个准确的数字,为何0.1+0.1没有问题这个我还没仔细研究,不过我猜想是因为本身计算就是一个计算近似值的过程因此再得出结果后,如果还在一个近似范围内就会认为没有误差,超过这个范围则会认为出现误差了,总之我们可以确认的是计算過程中拿到的确实是一个近似数了这个也确实是导致一些浮点数计算丢失精度的原因~

有兴趣的话可以到这里查看实际的数字在计算机中存储的具体内容~

我要回帖

更多关于 0乘以1等于0为什么 的文章

 

随机推荐