type
status
date
slug
summary
tags
category
icon
password
十进制小数转二进制小数
对十进制小数乘2得到的整数部分和小数部分,整数部分既是相应的二进制数码;
再用2乘小数部分(之前乘后得到新的小数部分),又得到整数和小数部分;
如此不断重复,直到小数部分为0或达到精度要求为止。
第一次所得到为最高位,最后一次得到为最低位。
如:
0.8125的二进制:
0.81252=1.625 取整是1
0.6252=1.25 取整是1
0.252=0.5 取整是0
0.52=1.0 取整是1
即0.8125的二进制是0.1101(第一次所得到为最高位,最后一次得到为最低位)
0.1 的二进制:
乘数 | 乘2结果 | 整数部分 | 说明 |
0.1 | 0.2 | 0 | ㅤ |
0.2 | 0.4 | 0 | ㅤ |
0.4 | 0.8 | 0 | ㅤ |
0.8 | 1.6 | 1 | 减1 |
0.6 | 1.2 | 1 | 减1 |
0.2 | 0.4 | 0 | ㅤ |
0.4 | 0.8 | 0 | ㅤ |
0.8 | 1.6 | 1 | 减1 |
0.6 | 1.2 | 1 | 减1 |
… | … | … | ㅤ |
可见,十进制 0.1 转为二进制后为
0.000110011001100110011...
无限循环小数计算机浮点数表示
计算机存储浮点数遵循 IEEE 754 格式。
V = (-1)^S * M * 2^E
- S(Sign/1bit):符号部分,当 S=0,V 为正数;当 S=1,V 为负数。
- E(Exponent/8bits):指数部分。以2为底。需要注意的是,E 在这里是一个无符号整数,但是实际上指数是可以存在负数的,所以 IEEE 754 规定,E 需要偏移127(64位为1023),如,2^10 的指数是10,保存成32位浮点数时,必须保存成 10+127=137,即10001001。
- M(Mantissa/23bits):表示有效数字,大于等于1,小于2。第一位 1 可以被舍去,只保留小数部分节省一位有效数字。
指数 E 还分为三种情况:
- E 不全为0或不全为1。这时,浮点数就采用上面的规则表示,即指数E的计算值减去127(或1023),得到真实值,再将有效数字M前加上第一位的1。
- E全为0。这时,浮点数的指数E等于 1-127(或者 1-1023),有效数字M不再加上第一位的1,而是还原为 0.xxxxxx 的小数。这样做是为了表示±0,以及接近于0的很小的数字。
- E全为1。这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位s);如果有效数字M不全为0,表示这个数不是一个数(NaN)。
IEEE 754 中规定:
对于32位的浮点数,最高的1位是符号位S,接着的8位是指数E,剩下的23位为有效数字M;
对于64位的浮点数,最高的1位是符号位S,接着的11位是指数E,剩下的52位为有效数字M。
计算误差
下面以双精度 double 类型的 0.1+0.2 为例
可以发现,由于十进制下的部分小数无法使用二进制精确表示,所以会存在一定的计算误差。在平常应用中我们很少会遇到这个问题,比如遇到支付宝这样的货币系统,需要高精度的计算时,通常我们会定义精确到小数点后两位,然后使用整形来代替浮点型,即使用一分钱的整数倍。