为什么计算机中计算小数时可能产生误差?
计算机中的小数是通过二进制科学计数法表示的,通过尾数*2^指数表示,当尾数过长时会被截断,截断后就会产生误差。
像十进制0.1这样的,无法通过2的负数次方表示出来,只能截断表示近似数,就会出现误差。
浮点数是采用科学计数法的方式来表示的,例如十进制小数 8.345,用科学计数法表示,可以有多种方式:
8.345 = 8.345 * 10^0
8.345 = 83.45 * 10^-1
8.345 = 834.5 * 10^-2
...
小数点的位置就变得「漂浮不定」了,这就是相对于定点数,浮点数名字的由来。
使用同样的规则,对于二进制数,我们也可以用科学计数法表示,也就是说把基数 10 换成 2 即可。
V = (-1)^S * M * 2^E
S:符号位,取值 0 或 1,决定一个数字的符号,0 表示正,1 表示负
M:尾数,用小数表示,例如前面所看到的 8.345 * 10^0,8.345 就是尾数
E:指数,用整数表示,例如前面看到的 10^-1,-1 即是指数
将十进制数 25.125 转换为浮点数,转换过程就是这样的(D代表十进制,B代表二进制):
- 整数部分:25(D) = 11001(B)
- 小数部分:0.125(D) = 0.001(B)
- 用二进制科学计数法表示:25.125(D) = 11001.001(B) = 1.1001001 * 2^4(B)
所以符号位 S = 0,尾数 M = 1.001001(B),指数 E = 4(D) = 100(B)
1985年,IEEE 组织推出了浮点数标准,就是我们经常听到的 IEEE754 浮点数标准,这个标准统一了浮点数的表示形式,并提供了 2 种浮点格式:
- 单精度浮点数 float:32 位,符号位 S 占 1 bit,指数 E 占 8 bit,尾数 M 占 23 bit
- 双精度浮点数 float:64 位,符号位 S 占 1 bit,指数 E 占 11 bit,尾数 M 占 52 bit
为了使其表示的数字范围、精度最大化,浮点数标准还对指数和尾数进行了规定:
- 尾数 M 的第一位总是 1(因为 1 <= M < 2),因此这个 1 可以省略不写,它是个隐藏位,这样单精度 23 位尾数可以表示了 24 位有效数字,双精度 52 位尾数可以表示 53 位有效数字
- 指数 E 是个无符号整数,表示 float 时,一共占 8 bit,所以它的取值范围为 0 ~ 255。但因为指数可以是负的,所以规定在存入 E 时在它原本的值加上一个中间数 127,这样 E 的取值范围为 -127 ~ 128。表示 double 时,一共占 11 bit,存入 E 时加上中间数 1023,这样取值范围为 -1023 ~ 1024。
作者:Kaito 链接:https://zhuanlan.zhihu.com/p/339949186 来源:知乎