标签: IEEE标准

  • 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.