function to64bitFloat(number) {
var i, result = "";
var dv = new DataView(new ArrayBuffer(8));
dv.setFloat64(0, number, false);
for (i = 0; i < 8; i++) {
var bits = dv.getUint8(i).toString(2);
if (bits.length < 8) {
bits = new Array(8 - bits.length).fill('0').join("") + bits;
}
result += bits;
}
return result;
}
参考:
ECMAScript文档写明,数字类型遵循IEEE 754标准的64位双精度格式存储。这种类型用于存储整数和分数,等同于Java和C中的
double
数据类型。JavaScript的一些新开发人员没有意识到这一点,并且相信如果他们使用1,它将以64位存储为:0000000000000000000000000000000000000000000000000000000000000001
实际上存储形式是这样的:
0011111111110000000000000000000000000000000000000000000000000000
继续深入,了解为什么存储的格式与想象的不一样。
科学计数法,小学的时候学过,忘的差不多,回顾一下。 根据wiki定义,有效位数取值范围为0<=|significant|<base,因此正确表示为
significant表示有效位数,也被称为mantissa或precision。base表示统计的基数。exponent表示小数点向左向右移多少位,也叫指数。
任何数都可以用科学计数法来表示。如十进制和二进制系统中的数2可以表示为:
然后看一个小数如何表示:
指数大于0,表示小数点右移;指数小于0,表示小数点左移。
科学计数法可以用来表示数字的浮点数。进一步理解为浮点数就是小数点的移位。
IEEE754定义了两种精度存储方式——单(32)精度/双(64)精度
Javascript使用64位存储数字,下面是它如何以JavaScript的Number类型使用的双精度格式(每个数字为64位)分配这些位:
符号位占1位,指数占11位,52位分配给尾数(有效数字)
1的浮点数
1的科学计数法表示如下:
有效位是1,指数是0,可以得出如下表示:
0 00000000000 0000000000000000000000000000000000000000000000000001
然而,我们如何计算实际存储的格式呢?网上搜到一种方法可以计算出浮点数的存储格式:
打印结果得到:
0 01111111111 0000000000000000000000000000000000000000000000000000
尾数占位符没有数字,指数中存在1。大大的疑问??二进制中最高有效位始终为1,所以不存储,在执行数学运算时,第一个数字1由硬件前置。数字1在标准化形式的小数点之后没有数字,并且没有存储小数点之前的第一个数字,因此我们没有任何东西可以放入尾数,因此它全部为零。 指数存储是通过位偏移计算,得到的结果:
因此就计算出了指数占位符中的数。
3的浮点数
3的二进制是11,科学计数法如下:
小数点后只有一个1需要存储,小数点前的1不存储;然后根据指数的位偏移计算指数占位符:
关于尾数的一件事要注意,数字按照它们以科学形式放置的确切顺序存储 - 从小数点开始从左到右。考虑到这一点,让我们将所有数字放在浮点表示中:
0.1+0.2 !== 0.3
现在再来看看0.1加0.2为什么不等于0.3
0.1和0.2的浮点数
根据二进制转换规则,0.1是一个无线循环的小数:
用科学计数法表示如下:
由于尾数只能有52位,我们需要在小数点后将无限数舍入为52位。
指数的计算根据位偏移得出:
因此0.1的存储形式如下:
同样的方法,0.2的存储形式为:
0.1/0.2的科学计数法表示如下:
计算两个数相加,需要使得指数相同。调整后的0.1如下:
然后两数相加:
现在,计算结果以浮点格式存储,因此我们需要对结果进行标准化,必要时进行舍入并计算偏移二进制的指数。
当转换为浮点格式进行存储时,它具有以下位模式:
这正是执行语句0.1 + 0.2时存储的位模式。为了得到它,计算机必须绕三次 - 每个数字一个,第三次总和。当存储简单的0.3时,计算机仅执行一次舍入。这种舍入操作导致存储0.1 + 0.2和独立0.3的不同位模式。当JavaScript执行比较语句0.1 + 0.2 === 0.3时,它们的这些位模式被比较,并且由于它们不同,返回的结果是假的。
NaN/Infinity
这两个指数是1024,不等于Number.MAX_VALUE(指数是1023) NaN的存储形式为:
Infinity是浮点数的另一个特例,用于处理溢出和一些数学运算,如1/0。无穷大用指数中的所有1和尾数中的全零表示