一、场景描述
发现js把response中的数据转成json格式之后,值不一样了。
原因:在js中Number类型统一按浮点类型处理,大整数的精度丢失和浮点数本质上是一样的,尾数位最大是 52 位,因此 JS 中能精准表示的最大整数是 Math.pow(2, 53),十进制即 9007199254740992,大于 9007199254740992 的可能会丢失精度。
解决:后台把Long转成string在返回给前段。
二、浮点数简介
对于浮点类型的数据采用单精度类型(float)和双精度类型(double),按照浮点数存储标准(IEEE 制定)来存储,float数据占用32bit,double数据占用64bit。
单精度的存储方式如下图所示:
双精度的存储方式如下图所示:
三、浮点数转二进制
例如:9.2转二进制
整数部分:9 ==> 1001
小数部分转二进制:小数乘以2,取整,小数部分继续乘以2,取整,得到小数部分0为止,将整数顺序排列.
比如0.2
0.2 * 2 = 0.4,取整0,小数部分0.4
0.4 * 2 = 0.8,取整0,小数部分0.8
0.8 * 2 = 1.6,取整1,小数部分0.6
0.6 * 2 = 1.2,取整1,小数部分0.2
….无限循环
即为0011*N
四、浮点数的二进制存储
-
-
-
- 符号位:0表示正数,1表示负数.
- 对于指数部分N,因为指数可正可负,8位的指数位能表示的指数范围就应该为:-127~128,所以可以对他进行置偏,根据浮点数的存储标注(IEEE),float 类型的指数起始数为127(二进制0111 1111),double类型的指数起始数为1023(二进制011 1111 1111),在此基础上加指数,得到的就是内存中的指数的表示形式.所以指数部分的存储采用移位存储,存储的数据为32位则元数据+127 ,64位则+1023
- 尾数则直接填入,位数不够则补0,位数过多则0舍1入
-
-
举个栗子:9.125
整数部分:9.125==>9==>1001
小数部分:
0.125 * 2 = 0.25 ==> 取整0,余数0.25 ==>0
0.25 * 2 = 0.5 ==> 取整0,余数0.5 ==>0
0.5*2 = 1.0 ==> 取整1 ==>1
拼接后9.125 ==> 1001.001==> 1.001001*2^3
1.001001 * 2^3 ==>
0 127 +3 0010 01 ==>
0 1000 0010 0010 01 ==> 0100 0001 0001 0010 0000000000000000
五、浮点数精度丢失
2.2转换成二进制为0 0111 1110 00110011001100110011 ….无穷,但是因为 float 和 double 存储的位数都有限,那么超出位数部分的肯定就被截断了。
这就导致2.2最终被保留下来的可能就是:
0 (1位符号位) 0111 1110(8位指数位) 00110011001100110011…(23位位数)