浮点数

来自GSXAB的知识库
浮点数
术语名称 浮点数
英语名称 floating-point number
符号位
术语名称 符号位
英语名称 sign bit
有效数
术语名称 有效数
英语名称 significand
别名 有效数字
尾数
术语名称 尾数
英语名称 mantissa
别名 trailing significand
指数
术语名称 指数
英语名称 exponent
阶码
术语名称 阶码
英语名称 biased exponent
规格化数
术语名称 规格化数
英语名称 normal number
别名 normalized number
非规格化数
术语名称 非规格化数
英语名称 subnormal number
别名 denormalized numbers, denormal numbers

浮点数(floating-point number, FP)是一类计算机内的数的表示方法(机器数)的统称。类似科学记数法,小数被分为符号位指数尾数/有效数三部分,分别存储于指定位数的二进制位中。

浮点数这一称呼与固定小数点位置,将多余位数全部用于保存真实值的定点数相对。由于浮点数中指数可以在一定范围内改变,浮点数比定点数能表达变化范围更大的数据,而且可以处理极大或极小的数值;但是浮点数由于比相等位数的定点数表示有效数字的部分减少了位数,而且最低有效位所实际对应的数位随指数改变,相对精度更加有限,且在相对精度大致固定的情况下,绝对精度随着数字本身的大小发生不均匀的变动。

定义

浮点数(floating-point number)是一类实数表示法,其存储三个位段:

  • 符号位(sign bit),一般是最高位,有 0 (正)和 1 (负)两个取值。对应数值一般记作 [math]\displaystyle{ S=\pm 1 }[/math]
  • 有效数(significand)部分。对应科学记数法中的有效数字的部分。由于二进制科学记数法中,有效数字的整数部分必定为 1 ,存储时省略掉,因此称为隐藏位(hidden bit),实际保存的是后续的小数部分,因此称为尾数(mantissa / trailing significand)部分[1],记作 [math]\displaystyle{ M }[/math]
  • 指数(exponent)部分。对应科学记数法中的指数。由于指数是有符号数,常常根据所需要表达的范围加上一定偏移值 [math]\displaystyle{ B }[/math] 以全部移动到非负范围(即移码)便于运算,这种被移动过的编码也称为阶码(biased exponent),以防止与“指数”的真值混淆,记作 [math]\displaystyle{ E }[/math]

注意:这里存在两套用于不同语境的术语:在逻辑上、在数学相关的学术语境上,浮点数包括浮点数、指数、有效数三部分;而在工程中,或者在硬件存储语境中,浮点数包括符号位、阶码、尾数三部分。其中阶码是指数部分的硬件表示,尾数是有效数部分的硬件表示。可以认为是数学实体和存储编码的两套语境。

按以上记号,一个浮点数所表示的真值为 [math]\displaystyle{ S (1 + M) \cdot 2^{E - B} }[/math] ,所使用的二进制位的位数为 [math]\displaystyle{ (1+n_M+n_E) }[/math] 位。

这里表达的是绝大多数浮点数,因此假定了浮点数的有效数字都以 1 开头,也就是符合标准的科学记数法形式,这种情况称为规格化数(normal numbers / normalized numbers)。在标准的实践中,为了表达一些不便于使用规格化表达的数(如 0 和其他接近 0 的数),也会使用一些不符合这一规则的特殊值,称为非规格化数(subnormal numbers / denormalized numbers)。

floating_point_number.svg

子格式

浮点数因为结构复杂,需要称为浮点运算单元(FPU)的硬件单独处理,支持其四则运算及其他复杂操作。这使得浮点数通常只使用标准位数的指定格式,通常遵循的标准为 IEEE 754

由于近年来深度神经网络发展,又出现了指数部分变化范围更大、尾数部分精度需求较低的浮点数,也就是 bfloat16 等浮点数。

由于浮点数需要单独根据各段长度定制化处理,并不会产生一种表达任意位浮点数的方法,非标准浮点数也相当少见。

运算

浮点数运算涉及大量的硬件算法,以保证硬件可以以较小开销直接快速支持。

由于本 wiki 主要讲述软件知识,避免过多展开硬件算法,只进行简单介绍。

规格化

规格化(normalization)指将有效数字不符合科学记数法,或者说不是规格化(normalized)数的表达变成规格化数的过程。朴素地检查最高位有效数字(即最高位的 1 )是否处在隐藏位该在的位置上,并按需要进行左移右移并增减阶码。

浮点加减法

包括四个步骤:

  • 对阶:指将指数部分较小的浮点数尾数右移至两数阶码相同。
  • 尾数相加:通过并行加法器对小数点已经对齐的两个数据进行加法(若为减法,执行补码加法)。需要保证额外的保护位(guard bit)处理溢出,黏性位(sticky bit)处理被对阶操作移动到尾数外的位,以保证后续舍入能判断后续位要如何舍入。
  • 规格化:在上一步中,相加结果可能向前溢出一位或存在前导 0 ,此时对其执行规格化。
  • 舍入处理:按规则舍弃规格化后超出尾数部分的多余位。

浮点数的加法因为存在对阶和舍入,是有精度下降以及运算误差的。经过多次浮点运算后会形成累计误差,而且也不满足结合律

浮点乘法

由于阶码和尾数在乘法中可以单独运算,浮点数的称除法也处理成几个部分。

  • 符号位处理:符号位进行异或。
  • 指数相加:将阶码相加再减去一次偏移值,以避免结果带有两次偏移。
  • 尾数相乘:补全隐藏位然后进行乘法,过程中处理进位,可能需要两倍长度的位数来处理全部进位。这里可能使用 Booth 算法等。
  • 规格化
  • 舍入处理
  • 特殊值:对 0 等特殊值,直接按照特殊值规则产生结果。


数的内部表示
十进制数的二进制编码 BCDGray 码奇偶校验码 、 字符表示
整数的机器数 定点整数 无符号定点整数
有符号定点整数(原码反码补码移码
小数的机器数 定点小数浮点数IEEE 754
  1. 尾数的 mantissa 一词因为词源是借用自计算常用对数时的小数部分,有观点认为用在这里指真数的小数部分会造成误解,所以较新的材料中不推荐使用这一词汇而是用 trailing significand 表示这一概念。