IEEE-754双精度浮点数
IEEE二进制浮点数算术标准(IEEE 754)规定了四种表示浮点数值的方式:单精确度(32位)、双精确度(64位)、延伸单精确度(43比特以上,很少使用)与延伸双精确度(79比特以上,通常以80位实现),本文介绍64位双精度浮点数。
存储结构
IEEE-754双精度浮点数(double floating-point)存储为64bit,由符号位(s)、有偏指数(e)、小数部分(f)组成:
组成
描述
位数
位置
sign
符号,0表示正,1表示负
1bit
63
exponent
指数部分
11bit
52-62
fraction
小数部分
52bit
0-51
类型划分
11位的指数部分可存储00000000000 ~ 11111111111(十进制范围为0 ~ 2047),取值可分为3种情况:
11位指数不为00000000000和11111111111,即在00000000001 ~ 11111111110(1 ~ 2046)范围,这被称为规格化。
指数值为00000000000(0),这被称为非规格化
指数值为11111111111(2047),这是特殊值,有两种情况:
当52位小数部分f全为0时,若符号位是0,则表示+Infinity(正无穷),若符号位是1,则表示-Infinity(负无穷)
当52位小数部分f不全为0时,表示NaN(Not a Number)
规格化
规格化下,浮点数的形式可表示为:
(
−
1
)
s
×
1.
b
b
b
⋯
b
⏟
f
(
有
效
52
位
)
(
c
c
c
⋯
⏟
53
位
及
以
后
)
×
2
e
−
1023
(
0
<
e
<
2047
)
(-1)^s\times1.\underbrace{bbb\cdots b}_{f(有效52位)}(\underbrace{ccc\cdots}_{53位及以后})\times2^{e-1023} \quad (0< e < 2047)
( − 1 ) s × 1 . f ( 有 效 5 2 位 )
b b b ⋯ b ( 5 3 位 及 以 后
c c c ⋯ ) × 2 e − 1 0 2 3 ( 0 < e < 2 0 4 7 ) 其中:
s
为0或1,0表示正数,1表示负数,对应1bit的符号位
f
为52位有效位,其中的每一位b
是0或1,对应52bit的小数部分(不足52位补0)
c
是超出52位的部分(如果有的话,需要舍入(精度会丢失),规则下述)
e
为十进制数值,其11位的二进制数值对应11bit的指数部分
1023
为移码
,移码值为
2
n
−
1
−
1
2^{n-1}-1
2 n − 1 − 1 ,这里的n表示指数位数,对于64bit的双精度存储,n是11
十进制中,12345可表示为
1.2345
×
1
0
4
1.2345\times10^4
1 . 2 3 4 5 × 1 0 4 ;二进制中,10011可表示为
1.0011
×
2
4
1.0011\times2^4
1 . 0 0 1 1 × 2 4
先看个简单例子,计算2.25的双精度浮点数:
2.25转为二进制为10.01,10.01转为上述表示法为
1.
001
⏟
f
×
2
1
1.\underbrace{001}_{\scriptsize{f}}\times2^1
1 . f
0 0 1 × 2 1 ,可得:
数值为正,因此符号位是0
小数为001,不足52位,补0,得到
0010000000000000000000000000000000000000000000000000
⏟
001
后
49
个
0
共
52
位
\underbrace{0010000000000000000000000000000000000000000000000000}_{001后49个0\quad共52位}
0 0 1 后 4 9 个 0 共 5 2 位
0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
指数e-1023 = 1,则 e = 1024,二进制值为
10000000000
⏟
11
位
\underbrace{10000000000}_{11位}
1 1 位
1 0 0 0 0 0 0 0 0 0 0
综上,将1位符号、11位指数、52位小数整合可得到2.25的双精度浮点数表示:
0
⏟
s
10000000000
⏟
e
0010000000000000000000000000000000000000000000000000
⏟
f
\underbrace{0}_{s}\underbrace{10000000000}_{e}\underbrace{0010000000000000000000000000000000000000000000000000}_{f}
s
0 e
1 0 0 0 0 0 0 0 0 0 0 f
0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 上述步骤反向操作可得到十进制值
上面这个例子中,小数部分不存在舍入的问题(位数小于52位),那么如果小数超出了52位,如何处理呢?有以下几种情况:
1、第53位是0,无需处理 2、第53位是1且53位之后全是0:
若第52位是0,无需处理;
若第52位是1,那么向上舍入
3、第53位是1,且之后不全是0:那么向上舍入
再看一个例子,计算23.3的双精度浮点数: 23.3转为二进制为
10111.0100110011001100110011001100110011001100110011001100
⋯
⏟
1100
循
环
10111.0100110011001100110011001100110011001100110011001100\underbrace{\cdots}_{1100循环}
1 0 1 1 1 . 0 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 循 环
⋯ 改写为
1.
0111010011001100110011001100110011001100110011001100
⏟
52
位
1100
⋯
⏟
1100
循
环
×
2
4
1.\underbrace{0111010011001100110011001100110011001100110011001100}_{52位}\underbrace{1100 \cdots}_{1100循环}\times2^4
1 . 5 2 位
0 1 1 1 0 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 循 环
1 1 0 0 ⋯ × 2 4 数值为正,因此符号位是0;指数e -1023 = 4,e = 1027 = 10000000011,因此指数部分是10000000011;小数位无限循环,53位是1且之后不全是0,符合上述规则3,因此向上舍入,第52位由0变为1,最终小数部分为:
0111010011001100110011001100110011001100110011001101
0111010011001100110011001100110011001100110011001101
0 1 1 1 0 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 1 整合后得到23.3的双精度浮点数表示:
0
⏟
s
10000000011
⏟
e
0111010011001100110011001100110011001100110011001101
⏟
f
\underbrace{0}_{s}\underbrace{10000000011}_{e}\underbrace{0111010011001100110011001100110011001100110011001101}_{f}
s
0 e
1 0 0 0 0 0 0 0 0 1 1 f
0 1 1 1 0 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 1
非规格化
非规格化可用以下形式表示(小数点前面是0):
(
−
1
)
s
×
0.
b
b
b
⋯
b
⏟
f
(
52
位
)
×
2
e
−
1022
(
e
=
0
)
(-1)^s\times0.\underbrace{bbb\cdots b}_{f(52位)}\times2^{e-1022} \quad (e=0)
( − 1 ) s × 0 . f ( 5 2 位 )
b b b ⋯ b × 2 e − 1 0 2 2 ( e = 0 ) 当
f
=
0
f=0
f = 0 (52位小数全为0)时,表示的值是0:
s
=
0
s=0
s = 0 表示-0,
s
=
1
s=1
s = 1 表示+0
特殊值
当
e
=
2047
e=2047
e = 2 0 4 7 (11位指数全为1)时:
若
f
>
0
f>0
f > 0 ,表示NaN
若
f
=
0
,
s
=
0
f=0,s=0
f = 0 , s = 0 ,表示+Infinity
若
f
=
0
,
s
=
1
f=0,s=1
f = 0 , s = 1 ,表示-Infinity
数值范围
1、在规格化中,当指数e最大(前10位为1,11位为0,即2046)且小数f最大(52位全为1)时,能表示出最大正值
,为
1.
111
⋯
11
⏟
52
个
1
×
2
2046
−
1023
=
111
⋯
11
⏟
53
个
1
000
⋯
00
⏟
971
个
0
1.\underbrace{111\cdots11}_{52个1}\times2^{2046 - 1023} = \underbrace{111\cdots11}_{53个1}\underbrace{000\cdots00}_{971个0}
1 . 5 2 个 1
1 1 1 ⋯ 1 1 × 2 2 0 4 6 − 1 0 2 3 = 5 3 个 1
1 1 1 ⋯ 1 1 9 7 1 个 0
0 0 0 ⋯ 0 0 转为十进制值为1.7976931348623157e+308
,则能表示的最小负值
为-1.7976931348623157e+308
。
2、在规格化中,当指数e最小(前10位为0,11位为1,即1)且小数f最小(52位全为0)时,能表示出最小正值
,为
1.
000
⋯
00
⏟
52
个
0
×
2
1
−
1023
=
0.
000
⋯
00
⏟
1021
个
0
1
1.\underbrace{000\cdots00}_{52个0}\times2^{1 - 1023} = 0.\underbrace{000\cdots00}_{1021个0}1
1 . 5 2 个 0
0 0 0 ⋯ 0 0 × 2 1 − 1 0 2 3 = 0 . 1 0 2 1 个 0
0 0 0 ⋯ 0 0 1 转为十进制值为2.2250738585072014e-308
,则能表示的最大负值
为-2.2250738585072014e-308
。
在非规格化中,指数e为0 1、当小数f最大(52位全为1)时,能表示出最大正值
,为
0.
111
⋯
11
⏟
52
个
1
×
2
−
1022
=
0.
000
⋯
00
⏟
1022
个
0
111
⋯
11
⏟
52
个
1
0.\underbrace{111\cdots11}_{52个1}\times2^{-1022} = 0.\underbrace{000\cdots00}_{1022个0}\underbrace{111\cdots11}_{52个1}
0 . 5 2 个 1
1 1 1 ⋯ 1 1 × 2 − 1 0 2 2 = 0 . 1 0 2 2 个 0
0 0 0 ⋯ 0 0 5 2 个 1
1 1 1 ⋯ 1 1 转为十进制值为2.225073858507201e-308
,则最小负值
为-2.225073858507201e-308
2、当小数f最小(前51位为0,52位为1)时,能表示出最小正值
,为
0.
000
⋯
01
⏟
第
52
位
为
1
×
2
−
1022
=
0.
000
⋯
00
⏟
1073
个
0
1
0.\underbrace{000\cdots01}_{第52位为1}\times2^{-1022} = 0.\underbrace{000\cdots00}_{1073个0}1
0 . 第 5 2 位 为 1
0 0 0 ⋯ 0 1 × 2 − 1 0 2 2 = 0 . 1 0 7 3 个 0
0 0 0 ⋯ 0 0 1 转为十进制值为5e-324
,则最大负值
为-5e-324
整数范围(精确整数,无精度丢失)
当 e - 1023 = 52,即e = 1075,小数f最大(52位全为1)时,能表示出最大安全正整数
,为
1.
111
⋯
11
⏟
52
个
1
×
2
52
=
111
⋯
11
⏟
53
个
1
1.\underbrace{111\cdots11}_{52个1}\times2^{52} = \underbrace{111\cdots11}_{53个1}
1 . 5 2 个 1
1 1 1 ⋯ 1 1 × 2 5 2 = 5 3 个 1
1 1 1 ⋯ 1 1 转为十进制值为
2
53
−
1
2^{53}-1
2 5 3 − 1 = 9007199254740991
,则能表示的最小安全负整数
为-9007199254740991
总结
1、javascript中的数值统一采用IEEE-754双精度存储,因此在计算时可能出现精度丢失,导致奇怪的结果,如 0.1 + 0.2 !== 0.3
2、下表列出了IEEE-754中的数值边界值,其中某些值对应javascript中的数值常量
-
最小负值
最大负值
最小正值
最大正值
最小安全负整数
最大安全正整数
规格化
-1.7976931348623157e+308
-2.2250738585072014e-308
2.2250738585072014e-308
1.7976931348623157e+308(Number.MAX_VALUE)
-9007199254740991(Number.MIN_SAFE_INTEGER)
9007199254740991(Number.MAX_SAFE_INTEGER)
非规格化
-2.225073858507201e-308
-5e-324
5e-324(Number.MIN_VALUE)
2.225073858507201e-308
x
x
IEEE 754可以表示的数值范围是:
[
−
1.7976931348623157
×
1
0
308
,
−
5
×
1
0
−
324
]
∪
[
5
×
1
0
−
324
,
1.7976931348623157
×
1
0
308
]
[-1.7976931348623157\times10^{308},-5\times10^{-324}] \cup [5\times10^{-324},1.7976931348623157\times10^{308}]
[ − 1 . 7 9 7 6 9 3 1 3 4 8 6 2 3 1 5 7 × 1 0 3 0 8 , − 5 × 1 0 − 3 2 4 ] ∪ [ 5 × 1 0 − 3 2 4 , 1 . 7 9 7 6 9 3 1 3 4 8 6 2 3 1 5 7 × 1 0 3 0 8 ] 超过1.7976931348623157e+308
为Infinity
,小于-1.7976931348623157e+308
为-Infinity
,在(-5e-324,5e-324)
之间的数显示为0