BigInt与IEEE-754
小数的进制转换
小数的十进制转换为二进制,二进制转换为十进制
- 十进制转换为二进制
20.25 = 20 + 1/4 = 16 + 4 + 1/4 = 10100.01- 二进制转换为十进制
10100.01 = 1 * 2 ** 4 + 1 * 2 ** 2 + 1 * 2 ** (-2)IEEE-754
IEEE二进制浮点数算术标准(IEEE 754)是20世纪80年代以来最广泛使用的浮点数运算标准,为许多CPU与浮点运算器所采用。
这个标准定义了:
- 表示浮点数的格式(包括负零-0)与反常值(denormal number)
- 一些特殊数值((无穷(Inf)与非数值(NaN))
- 这些数值的“浮点数运算符”
也指明了四种数值舍入规则和五种例外状况(包括例外发生的时机与处理方式)。
它规定了4种表示浮点数的方式:
- 单精度(32位)
- 双精度(64位)
- 延伸单精度(43位以上,但很少使用)
- 延伸双精度(79位以上,通常以80位实现)
浮点数表示
一个浮点数的实际值可以这样表示:
其中:
- sign表示符号位
- exponent表示指数偏移值,也称为
阶码
INFO
exponent等于指数的实际值+某个固定的值,IEEE-754规定这个固定值是2n-1-1,其中n为指数域长度
例如:32位单精度的指数域长度为8个比特,那么这个固定值就是28-1-1=127
- fraction表示分数值,有时也称为尾数。用于存储数值的小数部分
用公式表示如下:
用图表示如下:

各部分位数
单精度和双精度的各个部分位数长度如下:
| 类型 | 符号位 | 指数偏移值 | 尾数 |
|---|---|---|---|
| 单精度 | 1(最高位) | 8( [23,31) ) | 23( [0,23) ) |
| 双精度 | 1(最高位) | 11( [52,63) ) | 52( [0,52) ) |
以单精度为例,举例说明在IEE-754下浮点数的转换
十进制转换为浮点数
78.125 = 1001110.0012=1.0011100012 * 26
阶码部分:6+127=133=100001012,最终得到的32位浮点数表示为:
0_10000101_001110001000000000000002
WARNING
尾数部分只存储小数部分,IEEE-754规定最高位默认为1,故省略。在转换为十进制时自动加上
- 浮点数转换为十进制
0_10000101_001110001000000000000002
尾数部分为:1.0011100012
阶数部分为:100001012 = 133 => 133 - 127 = 6
最终转换为十进制表示下的数值为:1.0011100012 * 26 = 1001110.0012 = 78.125
INFO
在相互转换时,需要来回加或减2n-1-1(其中n为指数域长度),这样不是很麻烦么?
对于任意一个浮点数而言,它不仅仅符号位可能为负,而且指数部分也可能为负(例如0.125)。其实IEEE-754指定的这种计算规则,是为了确保指数部分恒为正数。
这样可以简化两个浮点数的比较过程,只需要按位从高到底进行比较即可
浮点表示法
以上介绍的时IEEE-754种最常见的规格化浮点表示法,此外还有零、非规格化、无穷、NaN这4种表示法。
以单精度为例:
| 类型 | 符号数 | 实际指数 | 指数偏移值 | 尾数 |
|---|---|---|---|---|
| 0 | 0 | -127 | 0 | 000 0000 0000 0000 0000 0000 |
| -0 | 1 | -127 | 0 | 000 0000 0000 0000 0000 0000 |
| 正无穷 | 0 | 128 | 255 | 000 0000 0000 0000 0000 0000 |
| 负无穷 | 1 | 128 | 255 | 000 0000 0000 0000 0000 0000 |
| NaN | * | 128 | 255 | 非全0 |
正数下,最大的非规格化数等于最小的规格化数。如果一个浮点数的指数部分为0,尾数部分不为0,那么这个数应该按照非规格化浮点数来解析
number
在JavaScript中,数字不分为整数类型和浮点型类型,所有的数字都是由浮点型类型。
JavaScript 采用 IEEE754 标准定义的 64 位浮点格式表示数字,一个数值可以容纳的最大值是 21024 - 1(指数为 1023,尾数为基于二进制的 0.1111…),可以通过 Number.MAX_VALUE 获得。
超过这个值的数会被替换为特殊的数值常量 Infinity。
极值:
- 最大值(Number.MAX_VALUE)为 ±1.7976931348623157e+308
- 最小值(Number.MIN_VALUE)为 ±5e-324。
只有在 -253 + 1 到 253 - 1 范围内(闭区间)的整数才能在不丢失精度的情况下被表示(可通过 Number.MIN_SAFE_INTEGER 和 Number.MAX_SAFE_INTEGER 获得),因为尾数只能容纳 53 位(包括前导 1)。
超出这个范围的值就无法保证比较是正确的,例如:
2 ** 53 === 2 ** 53 + 1; // true如果需要对超出这个范围的值进行运算,可以通过ES6提供的BigInt对象
BigInt
BigInt 是一种内置对象,它提供了一种方法来表示大于 2^53 - 1 的整数。这原本是 Javascript 中可以用 Number 表示的最大数字。BigInt 可以表示任意大的整数。
不过,它不适合加密,因为它并没有考虑防止时序攻击
INFO
什么是时序攻击?
在给定的算法中,如果输入值不同,程序的执行时间也会不同。攻击者可以根据执行时间,不断调整输入值位数上的值来得到正确的输入值。
解决方案:
给定一个标志位,即使不同的输入值,也只会在给定时间节点返回。
参考:
【3】IEEE 754
【5】Number
【6】BigInt

