#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将doublevalue=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 source(__snprintf())中将snprintf()替换为misc/efgcvt_r.c,并添加一些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二进制64倍的最小可能次正常值,在DBL_TRUE_MIN中定义为<float.h>)非常接近0。使用%f打印将生成一个不带指数的十进制表示,如果只需要8个小数位,则它们都将0并且输出与预期的一样0.00000000
你似乎认为%ffcvt应该产生相同的数字。只有数量级在110之间的数字才是正确的。对于您的示例,fcvt生成有效数字4.94,但十进制指数为-324
FLOAT_FMT_FLAG是一个非标准GNU扩展,用于告诉printf传递的浮点值是along double。标准C将此标志定义为自C99起L
如果您的目标是使用不提供fcvt的C库生成%.8e的输出,则可以使用并删除指数部分。

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

10-09 08:42