IEEE-754双精度浮点数

IEEE二进制浮点数算术标准(IEEE 754)规定了四种表示浮点数值的方式:单精确度(32位)、双精确度(64位)、延伸单精确度(43比特以上,很少使用)与延伸双精确度(79比特以上,通常以80位实现),本文介绍64位双精度浮点数。

存储结构

IEEE-754双精度浮点数(double floating-point)存储为64bit,由符号位(s)、有偏指数(e)、小数部分(f)组成:

双精度浮点总量用lua低版本能解析吗 双精度浮点类型_javascript

组成

描述

位数

位置

sign

符号,0表示正,1表示负

1bit

63

exponent

指数部分

11bit

52-62

fraction

小数部分

52bit

0-51

类型划分

11位的指数部分可存储00000000000 ~ 11111111111(十进制范围为0 ~ 2047),取值可分为3种情况:

  1. 11位指数不为00000000000和11111111111,即在00000000001 ~ 11111111110(1 ~ 2046)范围,这被称为规格化。
  2. 指数值为00000000000(0),这被称为非规格化
  3. 指数值为11111111111(2047),这是特殊值,有两种情况:
  • 当52位小数部分f全为0时,若符号位是0,则表示+Infinity(正无穷),若符号位是1,则表示-Infinity(负无穷)
  • 当52位小数部分f不全为0时,表示NaN(Not a Number)

规格化

规格化下,浮点数的形式可表示为:
双精度浮点总量用lua低版本能解析吗 双精度浮点类型_浮点数_02
其中:

  • s为0或1,0表示正数,1表示负数,对应1bit的符号位
  • f为52位有效位,其中的每一位b是0或1,对应52bit的小数部分(不足52位补0)
  • c是超出52位的部分(如果有的话,需要舍入(精度会丢失),规则下述)
  • e为十进制数值,其11位的二进制数值对应11bit的指数部分
  • 1023移码,移码值为 双精度浮点总量用lua低版本能解析吗 双精度浮点类型_十进制_03,这里的n表示指数位数,对于64bit的双精度存储,n是11

十进制中,12345可表示为双精度浮点总量用lua低版本能解析吗 双精度浮点类型_javascript_04;二进制中,10011可表示为双精度浮点总量用lua低版本能解析吗 双精度浮点类型_双精度_05

先看个简单例子,计算2.25的双精度浮点数:

2.25转为二进制为10.01,10.01转为上述表示法为 双精度浮点总量用lua低版本能解析吗 双精度浮点类型_双精度浮点总量用lua低版本能解析吗_06,可得:

  • 数值为正,因此符号位是0
  • 小数为001,不足52位,补0,得到
    双精度浮点总量用lua低版本能解析吗 双精度浮点类型_浮点数_07
  • 指数e-1023 = 1,则 e = 1024,二进制值为双精度浮点总量用lua低版本能解析吗 双精度浮点类型_十进制_08

综上,将1位符号、11位指数、52位小数整合可得到2.25的双精度浮点数表示:
双精度浮点总量用lua低版本能解析吗 双精度浮点类型_双精度浮点总量用lua低版本能解析吗_09
上述步骤反向操作可得到十进制值

上面这个例子中,小数部分不存在舍入的问题(位数小于52位),那么如果小数超出了52位,如何处理呢?有以下几种情况:

1、第53位是0,无需处理
2、第53位是1且53位之后全是0:

  • 若第52位是0,无需处理;
  • 若第52位是1,那么向上舍入

3、第53位是1,且之后不全是0:那么向上舍入

再看一个例子,计算23.3的双精度浮点数:
23.3转为二进制为
双精度浮点总量用lua低版本能解析吗 双精度浮点类型_双精度_10
改写为
双精度浮点总量用lua低版本能解析吗 双精度浮点类型_十进制_11
数值为正,因此符号位是0;指数e -1023 = 4,e = 1027 = 10000000011,因此指数部分是10000000011;小数位无限循环,53位是1且之后不全是0,符合上述规则3,因此向上舍入,第52位由0变为1,最终小数部分为:
双精度浮点总量用lua低版本能解析吗 双精度浮点类型_双精度浮点总量用lua低版本能解析吗_12
整合后得到23.3的双精度浮点数表示:
双精度浮点总量用lua低版本能解析吗 双精度浮点类型_双精度_13


非规格化

非规格化可用以下形式表示(小数点前面是0):
双精度浮点总量用lua低版本能解析吗 双精度浮点类型_十进制_14
双精度浮点总量用lua低版本能解析吗 双精度浮点类型_双精度_15(52位小数全为0)时,表示的值是0:双精度浮点总量用lua低版本能解析吗 双精度浮点类型_双精度_16表示-0,双精度浮点总量用lua低版本能解析吗 双精度浮点类型_浮点数_17表示+0


特殊值

双精度浮点总量用lua低版本能解析吗 双精度浮点类型_javascript_18(11位指数全为1)时:

  • 双精度浮点总量用lua低版本能解析吗 双精度浮点类型_双精度浮点总量用lua低版本能解析吗_19,表示NaN
  • 双精度浮点总量用lua低版本能解析吗 双精度浮点类型_双精度浮点总量用lua低版本能解析吗_20,表示+Infinity
  • 双精度浮点总量用lua低版本能解析吗 双精度浮点类型_十进制_21,表示-Infinity

数值范围

1、在规格化中,当指数e最大(前10位为1,11位为0,即2046)且小数f最大(52位全为1)时,能表示出最大正值,为
双精度浮点总量用lua低版本能解析吗 双精度浮点类型_双精度浮点总量用lua低版本能解析吗_22
转为十进制值为1.7976931348623157e+308,则能表示的最小负值-1.7976931348623157e+308

2、在规格化中,当指数e最小(前10位为0,11位为1,即1)且小数f最小(52位全为0)时,能表示出最小正值,为
双精度浮点总量用lua低版本能解析吗 双精度浮点类型_双精度_23
转为十进制值为2.2250738585072014e-308,则能表示的最大负值-2.2250738585072014e-308


在非规格化中,指数e为0
1、当小数f最大(52位全为1)时,能表示出最大正值,为
双精度浮点总量用lua低版本能解析吗 双精度浮点类型_双精度浮点总量用lua低版本能解析吗_24
转为十进制值为2.225073858507201e-308,则最小负值-2.225073858507201e-308

2、当小数f最小(前51位为0,52位为1)时,能表示出最小正值,为
双精度浮点总量用lua低版本能解析吗 双精度浮点类型_十进制_25
转为十进制值为5e-324,则最大负值-5e-324

整数范围(精确整数,无精度丢失)

当 e - 1023 = 52,即e = 1075,小数f最大(52位全为1)时,能表示出最大安全正整数,为
双精度浮点总量用lua低版本能解析吗 双精度浮点类型_十进制_26
转为十进制值为双精度浮点总量用lua低版本能解析吗 双精度浮点类型_双精度_27 = 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可以表示的数值范围是:
双精度浮点总量用lua低版本能解析吗 双精度浮点类型_javascript_28
超过1.7976931348623157e+308Infinity,小于-1.7976931348623157e+308-Infinity,在(-5e-324,5e-324)之间的数显示为0