c - 为什么 snprintf 不适用于 double 0x1p-1074 ...?

标签 c linux glibc

#include<stdio.h>

int main()
{
        char *nstring = NULL;
        int n = 0, i = 0;
        double value = 0x1p-1074;
        char buf[128] = {0};

        n = snprintf(buf, 128,"%.*f", 8, value);

        while(i < n) {
                printf("buf[%d] : Data [%c]\n", i, buf[i]);
                i++;
        }

        return 0;
}

我在这里使用 snprintf 将 double value = 0x1p-1074 格式化为 buf。但是当我执行上面的代码时,我得到:

buf[0] : Data [0]
buf[1] : Data [.]
buf[2] : Data [0]
buf[3] : Data [0]
buf[4] : Data [0]
buf[5] : Data [0]
buf[6] : Data [0]
buf[7] : Data [0]
buf[8] : Data [0]
buf[9] : Data [0]

我尝试使用 glibc 函数 fcvt_r 使用 __snprintf() 如下格式化 0x1p-1074 如下:

 n = snprintf (buf, len, "%.*" FLOAT_FMT_FLAG "f", MIN (ndigit, NDIGIT_MAX),
                  value);

谁能解释一下 FLOAT_FMT_FLAG 的用法?我还尝试在 glib 源 (misc/efgcvt_r.c) 中用 snprintf() 替换 __snprintf() 并添加一些 printf;给出了我预期的输出:

buf[0] : Data [4]
buf[1] : Data [.]
buf[2] : Data [9]
buf[3] : Data [4]
buf[4] : Data []
buf[5] : Data []
buf[6] : Data []
buf[7] : Data []

这是预期的输出。我可以在我的测试程序中使用 FLOAT_FMT_FLAG 吗?或者有没有其他方法可以得到与 glibc 源代码相同的输出?

最佳答案

0x1p-1074 (IEEE-754 binary64 double 的最小可能次正规值,定义为 DBL_TRUE_MIN 中的 <float.h> )非常接近 0 .使用 %f 打印产生没有指数的小数表示,如果你只需要 8 位小数,它们都将是 0并且输出符合预期0.00000000 .

你似乎假设 %ffcvt应该产生相同的数字。仅适用于 1 之间的数字和 10在幅度上。对于您的示例,fcvt产生有效数字 4.94但十进制指数为 -324 .

FLOAT_FMT_FLAG是一个非标准的 GNU 扩展来告诉 printf传递的浮点值是 long double .标准 C 将此标志定义为 L从 C99 开始。

如果您的目标是生成 fcvt 的输出对于不提供它的 C 库,您可以使用 %.8e并去掉指数部分。

关于c - 为什么 snprintf 不适用于 double 0x1p-1074 ...?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51761285/

相关文章:

c - 如何获取C语言执行shell命令的响应结果?

c - 数组段错误结束

Linux 使用 grep 命令

linux - ubuntu伪分布式搭建Hadoop

c++ - 运行时错误 C++ 程序 : glibc detected, munmap_chunk(),无效指针

c - OpenCV:cvHoughCircles 使用错误

linux - Jenkins:如何包含来自不同 repo 协议(protocol)的脚本?

我可以让 valgrind 忽略 glibc 库吗?

linux - 在汇编中使用 printf 会导致管道输出为空,但在终端上有效

C - 线程同步