[英]Floating Point Representation in Hexadecimal using C Langauge
我输入了以下 C 代码:
typedef unsigned char* byte_pointer;
void show_bytes(byte_pointer start, size_t len)
{
int i;
for (i = 0; i < len; i++)
printf(" %.2x", start[i]);
printf("\n");
}
void show_float(float x)
{
show_bytes((byte_pointer) &x, sizeof(float));
}
void main()
{
float f = 3.9;
show_float(f);
}
这段代码的输出是:输出:0x4079999A
手动计算1.1111001100110011001100 x 2 幂 1
男:1111001100110011001100
E: 1 + 127 = 128(d) = 10000000(b)
最后位: 01000000011110011001100110011000
十六进制:0x40799998
尽管是 8,但为什么显示最后一个 A。
根据手动计算,十六进制的答案应该是:输出:0x40799998
那些未公开的人工计算肯定是错误的。 正确的结果是 4079999A 16 。
在通常用于float
、IEEE-754 binary32 或“单精度”的格式中,数字表示为一个整数,其大小小于 224,乘以一定范围内的 2 的幂。 (浮点表示通常以其他形式描述,例如符号、第一个数字后带有小数点的 24 位二进制有效数和 2 的幂。这些形式在数学上是等效的。)
这种形式中最接近 3.9 的两个数字是 16,357,785•2 −23和 16,357,786•2 −23 。 它们分别是 3.8999998569488525390625 和 3.900000095367431640625。 将它们排列起来,我们可以看到后者更接近 3.9:
3.8999998569488525390625 3.9000000000000000000000 3.9000000953674316406250
因为前者在小数点后第七位相差1.5,而后者在小数点后第八位相差约9.5。
因此,从 3.9 到这种float
格式的最佳转换会产生 16,357,786•2 −23 。 在十六进制中, 16,357,786 是 F9999A 16 。 在将表示编码为float
的位时,有效数的低 23 位被放入主要有效数字段。 低 23 位是 79999A 16 ,这就是我们应该在主要有效数字段中看到的。
另请注意,我们可以很容易地看到 3.9 的二进制文件是11.1110011001100110011001 1001100110011001100110… 2 。 粗体标记了适合float
有效数的 24 位。 紧随其后的是 1001...,我们可以看到它应该四舍五入,因为它超过了前一位的一半,因此有效数的最后四位应该是 1010。
(还要注意,好的 C 实现将源文本中的数字转换为最接近的可表示数字,尤其是对于没有很多十进制数字的数字,但 C 标准不要求这样做。它说“对于十进制浮点常量,以及十六进制浮点常量,当FLT_RADIX
不是 2 的幂,结果要么是最近的可表示值,要么是紧邻最近可表示值的较大或较小的可表示值,以实现定义的方式选择。但是,问题 40799998 16 中显示的编码, 不适用于相邻的可表示值 40799999 16和 4079999A 16 。它比任何一个都更远。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.