IEEE 754标准中的十进制浮点数#1:存储编码

作者:

似乎关于IEEE 754标准中十进制浮点数的中文资料不多,所以写了这篇。


什么是十进制浮点数

十进制浮点数(Decimal floating-point,DFP)是指以10为底数的浮点数表示法,主要解决的是二进制浮点数(Binary floating-point,BFP,常见的浮点数,底数为2)存在的精度问题(例如在财务计算等场景下,使用二进制浮点数经常无法满足需求)。

关于IEEE的十进制浮点数的一些历史。

  • IEEE 854中规范引入了十进制浮点数,但其标准不够完善,缺少对用来和其他系统交换的数据编码方式的规定。
  • IEEE 754-2008(IEEE浮点运算标准,此为2008年发布的修订版)中合并了IEEE 854中对十进制浮点数的规范,并且补全了之前的缺陷。ISO/IEC/IEEE 60559:2011标准与此标准内容相同。
  • IEEE 754-2019是现行有效的修订版本,相关的修改不是很多。

编码

和二进制浮点数相似,也有符号(Sign)、阶码(Exponent,指数)和尾数(Coefficient)三个部分。但不同点是它不一定都是规格化(Normalized)的,即尾数的最高位不一定是1,所以一些数值可以有多种表示方法,例如1×102=0.1×103;而且多了一个组合位(Combination field),用来扩展阶码和尾数的范围以提高存储空间利用率;剩下的“剩余位”,就是组合位组合剩下的(参见“具体规则”一节的“编码规则”小节)。

DFP的存储格式:

长度符号位组合位阶码剩余位(e)尾数剩余位(m)
32位(Decimal32)15620
64位(Decimal64)850
128位(Decimal128)12110
32k位(Decimal32k)2k+430k-10

DFP的数据范围:

长度尾数长度(十进制的数字位数)(p)指数范围(从0到x)数据最大值(Emax归一化后的数据最小值(Emin数据最小非零值(Etiny
32位719296-95-101
64位16768384-383-398
128位34122886144-6143-6176
32k位(3t)/10+1或者9k-23×2e=48×4k3×2e-11-Emax2-p-Emax

为了描述的简洁,后续的介绍中会引用表中的字母来代指对应的数据,对照如下:

  • e:阶码剩余位的长度
  • m:尾数剩余位的长度
  • p:尾数以十进制表示的数字位数
  • x:指数的最大取值

有效数字的两种不同编码方式

这两种不同的编码方式都可以用于编码阶码和尾数,且不论用哪种方式都不影响编码规则(数据范围相同)。

  • 二进制整数编码的有效位(Binary integer significand field,BIS或BID)
    • 它使用二进制整数(取值在0到(10p-1)之间)来编码有效数字。
    • 适合于在原本用于处理二进制的算数逻辑单元(ALU)上用软件实现DFP。
  • 紧凑十进制编码的有效位(Densely packed decimal significand field)
    • 紧凑十进制编码(Densely packed decimal,DPD)能更好地编码十进制数字,可以加快与二进制浮点数的相互转换。
    • 需要专用的ALU来提高效率,适合用硬件实现的DFP。
    • DPD编码是一种效率较高的BCD编码,但其细节不属于本文的内容,可以参考它的维基百科页面(本文的引用[3])。

具体规则

对阶码和尾数的约束

阶码最多(2+e)位,最高2位二进制只能取00、01、10。

尾数最多(4+m)位,最高4位二进制只允许0000~1001(即十进制的0~9)。

编码规则

符号位的定义和二进制浮点数中的相同,0表示正数,1表示负数。

当尾数的最高4位是0000~0111(即十进制的0~7)时,省略最高位相同的0,此时组合位前两位是阶码最高2位的三种取值,后三位是尾数剩下的000~111。

当尾数的最高4位是1000~1001(即十进制的8或9)时,省略最高3位相同的100,此时组合位的前两位是11,再往后两位是阶码最高2位的三种取值,最后一位是尾数剩下的0或者1。

余下的e位阶码和m位尾数分别存入阶码剩余位和尾数剩余位。

如果阶码或尾数的编码结果长度n不足以填充所有位时——即长度小于(2+e)或者(4+m),则先填满组合位,剩下的(e-n)或者(m-n)位在左侧补0。

特殊值的表示

正负无穷(±∞):组合位是11110,符号位表示正负。

静默NaN(Quiet NaN,QNaN):组合位为11111,阶码剩余位的最高位是0。

信号NaN(Signaling NaN,SNaN):组合位为11111,阶码剩余位的最高位是1。

对于这两种NaN,没有提到的所有位都会被忽略,因此初始化数组为NaN可以通过简单地把内存区域全部填充为某个字节来实现(例如全部填充0x7E=(0111 1110)b,会被解码为SNaN)。

这两种NaN的主要区别是QNaN用于表示计算无效,例如0/0等,它会静默传播,参与的所有运算结果都为QNaN;而SNaN用于快速失败(Fail-fast),在使用时产生异常。

参考资料

  1. IEEE Standards Association. IEEE Standard for Floating-Point Arithmetic: IEEE Std 754-2019[S]. New York: IEEE, 2019-07-22. ISBN: 978-1-5044-5924-2. DOI: 10.1109/IEEESTD.2019.8766229. ICS Code: 07.020, 35.080. Available at: https://ieeexplore.ieee.org/servlet/opac?punumber=8766227.
  2. Wikipedia contributors. Decimal floating point[EB/OL]. Wikipedia, The Free Encyclopedia. [2024-09-24]. [2024-11-16]. Available at: https://en.wikipedia.org/w/index.php?title=Decimal_floating_point&oldid=1247444055.
  3. Wikipedia contributors. Densely packed decimal[EB/OL]. Wikipedia, The Free Encyclopedia. [2024-06-30]. [2024-11-18]. Available at: https://en.wikipedia.org/w/index.php?title=Densely_packed_decimal&oldid=1237650875.

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注


The reCAPTCHA verification period has expired. Please reload the page.