众所周知 计算机是采用二进制进行存储的 整数转换为二进制存储就可以了 那么浮点数呢 计算机是没有办法存储小数点的 那么就要采用IEEE 754标准进行存储
那么这个标准是什么样子的呢 (`・ω・´)
- 第一段 占 1bit,表示符号位。代称为 S(sign)
- 第二段 占 8bits,表示指数。代称为 E(Exponent)。
- 第三段 占 23bits,表示尾数。代称为 M(Mantissa)。
S: 符号位 0代表正数 1代表负数
E: 指数位 相信学过数学的小伙伴应该都知道什么是指数 ,对于任何数来说 都可以满足
比如:对于 3 来说,因为 2 < 3 < 4,所以 n=1,而 n=E−127 所以E就等于128
还可以这样 比如 :3.15转换为二进制为 11.001000111101011100001010001111010111000010100011111
(进制之间的转换 大学应该都学过 没有学过的 请百度吧 ) 科学计数法的话 就是
1.1001000111101011100001010001111010111000010100011111 *2^1 (这是二进制 所以不要以为是10的几次方)
所以 n也是等于1的 (就是2的指数)
M: 尾数位 也就是小数位,但是这里叫偏移量可能好一些 根据上面二进制转换来说的话 比方:3.15的话
M= 1001000111101011100001010001111010111000010100011111(不要问我为什么要舍弃小数点前的1 因为就是这样) 因为float 的M位只能存储23个字节 所以M=10010001111010111000011(后面的都丢掉了 所以会失去准确性)
当然还可以这样认为 你可以认为,我们把一条线分成 2232232^23个线段,也就是 8388608 个线段。而存储的 M 值,就是从 2^n 到 x 要经过多少个段,也就是 2^n 到 x 的长度占 2^n+1 比例占的多少 假如还是3.14 (3.14 - 2) / (4 - 2) = 0.57, 而 0.57∗2^23=4781506.56 四舍五入 也就4781507 (上面其实也四舍五入了) 在转为二进制
最后 3.14 的二进制表示
我们再用 IEEE 754 的那个算式来算一下:
这个时候 就发现精度丢失了 (没错 就是在M处丢掉的)(╯︵╰)
double确实提高了精度 事实上也就是M段加长了 那么有没有不丢精度的办法呢 Java提供了一个 BigDecimal 类 不过相比较而言 运算速度上 可能就没有float 和double快了