c - 获取 unsigned int 或 float 的(float 的)尾数 (C)

标签 c ieee-754 mantissa

所以,我正在尝试编写一个函数,以其 (mantissa * 2^exponent) 格式打印给定的 float (n)。我能够得到符号和指数,但不能得到尾数(无论数字是多少,尾数始终等于 0.000000)。我拥有的是:

unsigned int num = *(unsigned*)&n;
unsigned int m = num & 0x007fffff;
mantissa = *(float*)&m;

对可能出现的问题有什么想法吗?

最佳答案

C 库包含一个执行此任务的函数,frexp :

int expon;
float mant = frexpf(n, &expon);
printf("%g = %g * 2^%d\n", n, mant, expon);

另一种方法是使用 log2fexp2f:

if (n == 0) {
  mant  = 0;
  expon = 0;
} else {
  expon = floorf(log2f(fabsf(n)));
  mant = n * exp2f(-expon);
}

对于相同的输入,这两种技术可能会给出不同的结果。例如,在我的计算机上,frexpf 技术将 4 描述为 0.5 × 23log2f 技术将 4 描述为 1 × 2 2。从数学上讲,两者都是正确的。此外,frexp 将为您提供尾数的确切位,而 log2fexp2f 可能会舍入最后一两位。


您应该知道 *(unsigned *)&n*(float *)&m 违反了反对“类型双关”的规则并且具有未定义的行为。如果您想获得与 float 具有相同位表示的整数,反之亦然,请使用 union :

union { uint32_t i; float f; } u;
u.f = n;
num = u.i;

(注意:大约从 2003 年开始,这种 union 的使用在 C 语言中就有了明确的定义,但是,由于 C++ 委员会长期以来没有充分注意进入 C 的变化,它在C++.)

您还应该知道 IEEE float 使用“有偏差”的指数。当您初始化一个 float 变量的尾数字段但将其指数字段保留为零时,这将为您提供一个具有大负数指数的数字表示:换句话说,一个数字太小了 printf("%f", n) 会将其打印为零。每当 printf("%f", variable) 打印零时,将 %f 更改为 %g%a并在假设 variable 实际上为零之前重新运行程序。

关于c - 获取 unsigned int 或 float 的(float 的)尾数 (C),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49804055/

相关文章:

c - Ater 增加 sleep() fd 无法正常工作

c# - FileSystemWatcher 无法访问文件,因为它正被另一个进程使用

performance - 现实世界中的 CPU 是否不使用 IEEE 754?

c - 为什么 MSVS 不优化 +0?

c++ - 如何在特定机器上找到尾数长度?

c - 在一种方法中使用两个信号量

c - C 函数的一个参数丢失

java - 如何在JAVA中提取IEEE 754浮点表示

javascript - 在javascript中将整数转换为数字的小数部分最有效的方法是什么?

c - 如何从 32 位 float 中提取符号、尾数和指数