gpt4 book ai didi

c - c中的十六进制浮点表示

转载 作者:太空狗 更新时间:2023-10-29 16:10:13 32 4
gpt4 key购买 nike

当我阅读 C 中的 float 的十六进制表示法时,我遇到了 Stephen Prata 书中的一个特殊数字“0xa.1fp10”。当我将这个数字分配给一个 float 或 double 变量并在 printf 中使用“%a”格式说明符打印它时,结果是 0x1.43e000p+13,与原来的不匹配。但两者都是相同的十进制值 10364。到底是怎么回事?为什么产值变了?如何获得原始数字作为输出?

最佳答案

不幸的是,您无法以可移植的方式获得相同 格式0xa.1fp10来自 printf . C 标准指定 %a 的输出是这样的 normal double 是非零的,在 . 之前 一个 非零数字以及表示恰好在 . 之后 的值所需的尽可能多的数字.该实现可以选择有多少位进入第一个数字!

但是C11标准有脚注278这就是说

Binary implementations can choose the hexadecimal digit to the left of the decimal-point character so that subsequent digits align to nibble (4-bit) boundaries.

这就是问题所在。由于 IEEE 754 double s 有 53 位尾数; normal 数字的第一位为 1;其余 52 位可被 4 整除,该脚注后面的实现(我机器上的 Glibc 似乎是一个)将总是输出任何有限的非零 float ,以便它开始与 0x1. !

例如尝试这个最小程序:

#include <stdio.h>

int main(void) {
for (double i = 1; i < 1024 * 1024; i *= 2) {
printf("%a %a %a\n", 1.0 * i, 0.7 * i, 0.67 * i);
}
}

我电脑上的输出是

0x1p+0 0x1.6666666666666p-1 0x1.570a3d70a3d71p-1
0x1p+1 0x1.6666666666666p+0 0x1.570a3d70a3d71p+0
0x1p+2 0x1.6666666666666p+1 0x1.570a3d70a3d71p+1
0x1p+3 0x1.6666666666666p+2 0x1.570a3d70a3d71p+2
0x1p+4 0x1.6666666666666p+3 0x1.570a3d70a3d71p+3
0x1p+5 0x1.6666666666666p+4 0x1.570a3d70a3d71p+4
0x1p+6 0x1.6666666666666p+5 0x1.570a3d70a3d71p+5
0x1p+7 0x1.6666666666666p+6 0x1.570a3d70a3d71p+6
0x1p+8 0x1.6666666666666p+7 0x1.570a3d70a3d71p+7
0x1p+9 0x1.6666666666666p+8 0x1.570a3d70a3d71p+8
0x1p+10 0x1.6666666666666p+9 0x1.570a3d70a3d71p+9
0x1p+11 0x1.6666666666666p+10 0x1.570a3d70a3d71p+10
0x1p+12 0x1.6666666666666p+11 0x1.570a3d70a3d71p+11
0x1p+13 0x1.6666666666666p+12 0x1.570a3d70a3d71p+12
0x1p+14 0x1.6666666666666p+13 0x1.570a3d70a3d71p+13
0x1p+15 0x1.6666666666666p+14 0x1.570a3d70a3d71p+14
0x1p+16 0x1.6666666666666p+15 0x1.570a3d70a3d71p+15
0x1p+17 0x1.6666666666666p+16 0x1.570a3d70a3d71p+16
0x1p+18 0x1.6666666666666p+17 0x1.570a3d70a3d71p+17
0x1p+19 0x1.6666666666666p+18 0x1.570a3d70a3d71p+18

此输出高效 - 对于每个普通 数字,代码只需要输出0x1.随后是转换为十六进制的尾数的所有实际半字节,带尾随 0字符并追加 p+后跟指数。


对于长 double ,x86 格式有 64 位尾数。由于 64 位可以精确地分为半字节,因此明智的实现将在 . 之前有一个完整半字节。对于 normal 数字,值从 0x8 变化至 0xF (第一位始终为 1),以及最多 15 个半字节。

尝试你的实现

#include <stdio.h>
int main(void) {
for (long double i = 1; i < 32; i ++) {
printf("%La\n", i);
}
}

看看是否符合这个期望...


在正正规数和零之间可以有次正规数 - 我的 Glibc 用 0x0. 表示这些 double 值后跟尾数的实际半字节,删除尾随零,以及固定指数 -1022 - 同样,表示是最容易实现和最快计算的表示。

关于c - c中的十六进制浮点表示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50670463/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com