本文介绍了为什么Swift使用基数2作为十六进制浮点值的指数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据Swift编程语言:

lockquote
例如,0xFp2表示15×2 ^ 2,
同样,0xFp-2代表15×2(-2),计算结果为3.75。



0xFp2 == 15 *(16 ** 2)而不是 0xFp2 == 15 *(2 ** 2) code
解析方案

Swift的十六进制浮点数表示法只是用于输入和输出(使用printf %a 格式)。

这个符号的目的是容易被人类解释,有些人可以识别出IEEE 754的表示方式。 IEEE 754表示使用基数2。因此,对于正常的浮点数,当 p 之前的数字在 1 和 2 , p 之后的数字直接是IEEE 754表示的指数字段的值。这符合人类可读性和与位代表性紧密相关的双重目标:

$ p $ $ $ $ $ $ $ $ $ $ $ $ $ $ #include< stdio.h>

int main(){
printf(%a\\\
,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 binary64数字的有效位数需要13个十六进制数字,在 0x1。之后才能完全表示,这是很多的,但是在二进制数字中需要52位数字,这是不切实际的。

十六进制的选择实际上有它的缺点:由于这个选择,相同数目的几个等价表示并不总是容易被认为是等价的。例如, 0x1.3p1 和 0x2.6p0 表示相同的数字,尽管它们的数字没有任何共同之处。在二进制中,这两个符号将对应于 0b1.0011p1 和 0b10.011p0 ,这会更容易看到当量。再举一个例子, 3.14 也可以表示为 0xc.8f5c28f5c28f8p-2 ,这是很难看到的与 0x1.91eb851eb851fp + 1 相同。如果在你的问题中提出的 p 后面的数字代表16的幂,那么这个问题就不存在了,但是当C99被标准化时,表示的唯一性并不是一个目标:接近IEEE 754的代表性。

According to The Swift Programming Language :

Why is 2 used as base for the exponent instead of 16? I'd have expected 0xFp2 == 15 * (16**2) instead of 0xFp2 == 15 * (2**2)

解决方案

Swift's hexadecimal notation for floating-point numbers is just a variation of the notation introduced for C in the C99 standard for both input and output (with the printf %a format).

The purpose of that notation is to be both easy to interpret by humans and to let the bits of the IEEE 754 representation be somewhat recognizable. The IEEE 754 representation uses base two. Consequently, for a normal floating-point number, when the number before p is between 1 and 2, the number after p is directly the value of the exponent field of the IEEE 754 representation. This is in line with the dual objectives of human-readability and closeness to the bit representation:

$ cat t.c
#include <stdio.h>

int main(){
  printf("%a\n", 3.14);
}
$ gcc t.c && ./a.out 
0x1.91eb851eb851fp+1

The number 0x1.91eb851eb851fp+1 can be seen to be slightly above 3 because the exponent is 1 and the significand is near 0x1.9, slightly above 0x1.8, which indicates the exact middle between two powers of two.

This format helps remember that numbers that have a compact representation in decimal are not necessarily simple in binary. In the example above, 3.14 uses all the digits of the significand to approximate (and even so, it isn't represented exactly).

Hexadecimal is used for the number before the p, which corresponds to the significand in the IEEE 754 format, because it is more compact than binary. The significand of an IEEE 754 binary64 number requires 13 hexadecimal digits after 0x1. to represent fully, which is a lot, but in binary 52 digits would be required, which is frankly impractical.

The choice of hexadecimal actually has its drawbacks: because of this choice, the several equivalent representations for the same number are not always easy to recognize as equivalent. For instance, 0x1.3p1 and 0x2.6p0 represent the same number, although their digits have nothing in common. In binary, the two notations would correspond to 0b1.0011p1 and 0b10.011p0, which would be easier to see as equivalent. To take another example, 3.14 can also be represented as 0xc.8f5c28f5c28f8p-2, which is extremely difficult to see as the same number as 0x1.91eb851eb851fp+1. This problem would not exist if the number after the p represented a power of 16, as you suggest in your question, but unicity of the representation was not an objective when C99 was standardized: closeness to the IEEE 754 representation was.

这篇关于为什么Swift使用基数2作为十六进制浮点值的指数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-23 09:45