根据 Swift编程语言:
例如,0xFp2代表15⨉2^ 2,其值为60。 类似地,0xFp-2代表15⨉2^( - 2),其值为3.75。
为什么2用作指数的基数而不是16?我原以为0xFp2 == 15 * (16**2)
而不是0xFp2 == 15 * (2**2)
答案 0 :(得分:11)
Swift的浮点数的十六进制表示法只是输入和输出notation introduced for C in the C99 standard的变体(使用printf %a
格式)。
该符号的目的是既易于人类解释,又让IEEE 754 representation的某些部分可以识别。 IEEE 754表示使用基数2。因此,对于正常的浮点数,当p
之前的数字介于1
和2
之间时,p
之后的数字直接是指数字段的值IEEE 754表示。这符合人类可读性和与位表示的紧密性的双重目标:
$ cat t.c
#include <stdio.h>
int main(){
printf("%a\n", 3.14);
}
$ gcc t.c && ./a.out
0x1.91eb851eb851fp+1
可以看到数字0x1.91eb851eb851fp+1
略高于3,因为指数为1
且有效数位于0x1.9
附近,略高于0x1.8
,这表明确切中间两个两权力之间。
这种格式有助于记住具有十进制紧凑表示的数字在二进制中不一定简单。在上面的示例中,3.14
使用有效数字的所有数字来近似(即使如此,它也没有完全表示)。
十六进制用于p
之前的数字,它对应于IEEE 754格式的有效数字,因为它比二进制更紧凑。 IEEE 754二进制64号的有效位数要求0x1.
之后的13个十六进制数字才能完全表示,这很多,但是需要二进制52位,这显然是不切实际的。
十六进制的选择实际上有它的缺点:由于这个选择,相同数字的几个等价表示并不总是容易识别为等价。例如,0x1.3p1
和0x2.6p0
代表相同的数字,尽管它们的数字没有任何共同之处。在二进制文件中,这两个符号对应于0b1.0011p1
和0b10.011p0
,这更容易被视为等效。再举一个例子,3.14
也可以表示为0xc.8f5c28f5c28f8p-2
,这很难看作与0x1.91eb851eb851fp+1
相同的数字。如果p
之后的数字代表16的幂,就像你在你的问题中所建议的那样,这个问题就不存在了,但是当C99被标准化时,表示的单一性不是一个目标:接近IEEE 754表示了。