类似float.h的定义,用于IEEE 754二进制16位半精度浮点数的定义。

4
我正在使用SoftFloat库中实现的半精度浮点数(即:100%符合IEEE 754标准的),为了完整起见,我希望为我的代码提供与floatdoublelong double<float.h> 中可用定义相等的定义。
我知道有不同类型的半精度浮点数,但我只关心由IEEE 754标准规定的标准化的一种,称为binary16
从我的研究和测试中,我可以自信地将某些常量定义如下:
#define HALF_MANT_DIG      11
#define HALF_DIG           3
#define HALF_DECIMAL_DIG   5
#define HALF_EPSILON       UINT16_C(0x1400) /* 0.00097656 */
#define HALF_MIN           UINT16_C(0x0400) /* 0.00006103515625 */
#define HALF_MAX           UINT16_C(0x7BFF) /* 65504.0 */

注意:epsilon,min和max是16位类型的原始十六进制表示。将原始值分配给类型的正确方法取决于所使用的半浮点库。

然而,对于指数相关的定义,我无法找到共识。我查看了二进制16的维基百科页面,这个其他SO问题Half库以及GitHub和其他地方的一些其他代码。

来自上述SO问题的提案链接听起来很可信,以及Half库,好消息是它们匹配。然而,我在FP16.java实现这个实现Zig语言实现以及D语言的Sargon中发现了不同意见。

#define HALF_MIN_EXP     The article and Half say (-13) but FP16.java and sargon say (-14) 
#define HALF_MAX_EXP     The article and Half say 16 but others say 14 or 15
#define HALF_MIN_10_EXP  The article and Half say (-4) but sargon says (-5)
#define HALF_MAX_10_EXP  The article and Half say 4 but sargon says 5

我认为这篇文章和Half很可能是正确的来源,但是,我能确定IEEE 754二进制16的好值吗?

1个回答

2

#define HALF_MANT_DIG 11

二进制16进制格式有11个有效数字(位)。(10个存储在主要的有效数字字段中,1个通过指数字段编码。)

#define HALF_DIG 3

我手头没有参考资料,所以无法评论。但这可以很容易地进行测试。

#define HALF_DECIMAL_DIG 5

IEEE 754-2019将其定义为1+ceiling(p×log10(2)),其中p是格式中“有效位数”,因此为11,因此1+ceiling(11•.3010299957) = 1+ceiling(3.3) = 1+4 = 5。

#define HALF_EPSILON UINT16_C(0x1400) /* 0.00097656 */

是的,使用11个有效数字,1用高位为2 0和低位为2 -10表示,即0.0009765625。它使用指数偏差15进行编码,因此指数字段中的5,因此5 << 11,即1400 16

#define HALF_MIN UINT16_C(0x0400) /* 0.00006103515625 */

是的,最小正常指数编码为1,去除偏差后得到-14,即0.00006103515625,并且指数字段中的1为 0400 16

#define HALF_MAX UINT16_C(0x7BFF) /* 65504.0 */

是的,最大正常指数字段为30,30 << 11给出7800 16,最大有效数字字段为1111111111 2= 3FF 16,将它们组合起来得到7BFF 16。去除15的指数偏差得到15,因此表示的值为2 15•(2−2-10) = 65,504。

#define HALF_MIN_EXP 文章和Half说(-13),但FP16.java和sargon说(-14)
#define HALF_MAX_EXP 文章和Half说16,但其他人说14或15

C语言定义了浮点数表示中尾数位于基数点后而非前面,并且在浮点格式的基数为b时,尾数范围是[1/b, 1)而不是[1, b)。这一点体现在*_MIN_EXP和*_MAX_EXP值以及frexp函数的行为上,而且指数与IEEE 754中常用的定义相差1。
根据IEEE 754标准,指数范围为[-14,15],因此C标准中的缩放范围为[-13,16]。
C 2018 5.2.4.2.2 12规定HALF_MIN_10_EXP的值为⌈log10b^(emin-1)⌉,其中emin为HALF_MIN_EXP,所以有⌈log10(2^-13-1)⌉=⌈-4.2144…⌉=-4。我们也知道从上文中的HALF_MIN可以得知10^(-4)在正常范围内而10^(-5)不在,因此-4是“最小的负整数,使得10的该幂次方在规范化浮点数的范围内”,这个解释也在5.2.4.2.2 12中。
类似地,C标准中将HALF_MAX_10_EXP规定为⌊log10((1-b^-p)b^emax)⌋,其中p为浮点数格式的尾数位数,emax为HALF_MAX_EXP,所以有⌊log10((1-2^-11)2^16)⌋=⌊log10(65,504)⌋=⌊4.8162…⌋=4。此外,10^4在HALF_MAX以下而10^5不在。

非常感谢您详细说明所有的检查!! - cesss

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接