处理精度丢之-浮点数在计算机中是如何存储的

平时项目开发中经常会遇到一些精度丢失的问题,像老生常谈的0.1 + 0.2 !== 0.3,只知道是计算机的二进制实现和位数限制,有些数无法有限表示,但却没认真去亲自检测过。今天心情好,来测试一把。

在此之前,我们先来复习一下还给老师的知识点

二进制转十进制

十进制转二进制:

    整数:

   

小数:

知道是怎么算就阔以了,快速转换进制,工具送上:https://tool.oschina.net/hexconvert/

在计算机中,我们存储一个数的存储结构由三小块组成,对应 符号位 、指数位、尾数位

符号位

简单清晰,占一位: 1代表负数, 0 代表正数

指数位

浮点数可分为单精度类型and双进度类型,单精度指数位: 占8位, 双进度指数位: 占11位。

对前端来说,我们知道JavaScript 存储小数和其它语言如 Java 和 Python 都不同,JavaScript 中所有数字包括整数和小数都只有一种类型 即 Number类型,是以64位双精度浮点数存储所有Number类型值,所以指数位占11位。

关于指数位的计算:

  • 计算机对于整数的存储只需要转换成对应的进制。相比于小数,小数点的位置无法确定,小数点后面的位数也无法确定。所以提出借助科学计数法解决,例如:11011.1 科学计数法转化为:1.10111 * 24,这样小数点的位置就确定下来了
  • 偏移量: 2k - 1,  k代表所占位数,像单精度占8位,双精度占11位,所以单精度指数偏移量为127, 双精度指数偏移量为1023
  • 指数位 = 偏移量 + 指数

以双精度来举例:

11011.1 科学计数法转化为:1.10111 * 24,因为是双精度,所以偏移量为1023, 指数为4, 所以指数位的值为1027(此时得到的值位十进制,需要转换成计算机识别的二进制)

再转化为二进制: 1000 0000 011 (tips: 转化的二进制不足位数时,记得补0,这里刚好是11位,不用补)

尾数位

  • 单精度占23位, 双精度占52位
  • 取转换为科学技术发后小数点后面的值就完事了(下方案例送上)

案例补充:

0.1

转化为二进制:

0.0001100110011001100110011001100110011001100110011001101

转科学计数法:

1.100110011001100110011001100110011001100110011001101 * 2-4

转实际存储:

正数: 0

指数位:1023 + (- 4 ) = 1019 转 二进制: 1111 1110 11 --》 指数位为11位,补0得到:01111111011

尾数位:1001100110011001100110011001100110011001100110011010

结果:0 01111111011 1001100110011001100110011001100110011001100110011010

tip: 指数位从前往后补0;尾数位从后往前补0;

27.5

转二进制:

11011.1

转科学技术法:

1.10111 * 24

转实际存储:

正数: 0

指数位:1023 + 4 = 1027 转二进制:1000 0000 011

尾数位:10111

结果:0 1000 0000 011 10111000000000


机器数0 1000 0000 011 10111000000000 转10进制

取符号位: 0为正数

取指数位:1000 0000 011 转10进制:1027,得到指数: 1027 - 1023 = 4

取尾数位:10111000000000

转科学技术法表示:1.10111000000000 * 24

转二进制:11011.1

转十进制:27.5

Next: 处理精度丢失之-如何解决

原文地址:https://www.cnblogs.com/Tiboo/p/13702637.html