摘要:本篇文章会讲述浮点数的设计原理,比如如何存储二进制的问题,从而帮助我们更好的编码。
__1. deading code __
console.log(1.0-0.9 == 0.1);
//输出 false
console.log(1.0-0.9, 0.1);
//输出 0.09999999999999998 0.1
//所以判断浮点运算结果前要对参数进行精度缩小,缩小精度会四舍五入。
console.log(parseFloat((1.0-0.9).toFixed(10)) == 0.1);
//输出 true
console.log(parseFloat((1.0-0.9).toFixed(10)),0.1)
//输出 0.1 0.1
所以使用 JavaScript 设计浮点数计算时,要考虑小数不准确的问题。
2.浮点数二进制存储
如 32 存储为例来讲解存储。
Sign | Exponent | Mantissa |
---|---|---|
1bit | 8bits | 23bits |
- Sign:表示浮点数是正数还是负数。0表示正数,1表示负数
- Exponent:指数部分。类似于科学技术法中的M*10^N中的 N,要注意规定
01111111 = 2^0 也就是 0,所以指数部分可以表达: -128 - 127。 - Mantissa:基数部分。浮点数具体数值的实际表示。
尝试把 3.1 转换成二进制存储:
- 是正数第一位是 0。
- 3 转换成二进制 11。
- 0.1 转换成二进制,__0.1 __ 转换成 0.0625+0.007825+0.00390625... 即 2-3+2-4+2^7....,二进制为 .00011001100110011001100 ,是1100无限循环,保留到23位。(这里确实有点绕,不理解的单独查资料能更快了解。也就是这里导致小数在计算机里的存储会不准确,是一个近似值。
- 整数和小数合并为 11.0001100110011001100110 , 然后保证小数点以前只有一位数,1.10001100110011001100110 * 2^1。
- 合并后小数点前的一位数是要舍去的,由于我们上一个步骤,小数点前的数字总会为 1,所以为了减少存储我们舍去 . 前的为1数字,最后得 .100011001100110011001100 * 2^1。
- 指数转换,由上一步得指数为 __2^1 __,由于规定 01111111 = 2^0(这样的目的就是为了,指数可以为正也可以为负), 2^1 为 10000000 ,合并后得
10000000 10001100110011001100110 - 添上第一位代表正负 0 10000000 10001100110011001100110 最终__ 3.1 __被用二进制表达。
其中最重要的部分是小数转二进制,像 0.5、0.25、0.125 这样的小数转化二进制为 0.1、0.01、0.001 ,但是 0.1、0.2 就不好表示了。如果不理解百度有在线二转十进制 地址
验证的网址:https://www.h-schmidt.net/FloatConverter/IEEE754.html
3.猜想
语言还没有组织好。
网友评论