什么是最长的字符串,可用"%1.17g"任何双精度浮点数的格式?

时间:2018-04-15 10:45:48

标签: c floating-point printf precision

我正在维护一个C json库,我需要知道sprintf输出的最大字符数是什么"%1.17g"格式字符串。目前我正在分配1100个字节(基于What is the maximum length in chars needed to represent any double value?),这看起来非常浪费。如果我理解正确,它应该永远不会超过22个字符(1表示整数部分,1表示点,16表示尾数,4表示" e-XX")。然而,浮点数的问题可能非常违反直觉,我不确定我是否错过了某些东西。我的推理是否正确?

2 个答案:

答案 0 :(得分:3)

继续发表评论,

%1.'.'之前的一个)指定最小字段宽度,它对可出现的位数没有限制。如果数字位数表示字段宽度,则字段将展开。

对于gG转换说明符,17指定“最大有效位数”。如果转换的指数小于-4或大于或等于精度,则使用“样式 e

  

e,E 双参数被舍入并以样式[-]d.ddde±dd转换,其中小数点前有一位数字   字符和后面的位数等于精度;   如果精度丢失,则取6;如果精度是   零,不显示小数点字符。 E转换使用。{   字母'E'(而不是'e')来介绍指数。该   指数始终包含至少两位数;如果值为零,   指数是00。

最大位数为:

'(+/-)' + 1 + '.' + 17 + 'e' + '(+/-)' + XXX + '\0' = 26-chars 

(其中XXX最多为308

为了获得良好的衡量标准,32个字符的缓冲区就足够了。 1100-char缓冲区没有任何问题。我宁愿是10,000字节太长,也不是1字节太短。

答案 1 :(得分:1)

  

对于任何双重

,可以使用“%1.17g”格式打印的最长字符串是什么

使用double使用各种样式打印// Large/small values in exponential notation printf("%1.17g\n", -1.0e200/7); printf("%1.17g\n", -1.0e-200/7); printf("%1.17g\n", -1.0e0/7); -1.4285714285714286e+199 -1.4285714285714286e-201 -1.4285714285714286e-06 // middle values in fixed notation printf("%1.17g\n", -1.0e-2/7); printf("%1.17g\n", -1.0e-5/7); -0.14285714285714285 -0.0014285714285714286 // non-finite values printf("%1.17g\n", -NAN); printf("%1.17g\n", -INFINITY); -nan /* this may be longer */ -inf

char

最长明显的字符串大小为25 sign digit point fraction e sign exponent null - 1 . 4285714285714286 e + 199 \0 1 1 1 17-1 1 1 3 1

double

这可能会更长?

  1. C允许非数字也包含有效负载,其中可能包含许多字符。 (我怀疑的不只是用十进制写的有效载荷.16 binary64
  2. 指数范围可能需要超过3个字符。 (可能是一个4或5位数的指数)
  3. double可能需要更多17位数来区分所有DBL_DECIMAL_DIG。 (可以double检测到)
  4. 目前的区域设置可能会为1添加额外字符(不太可能)
  5. "%1.17g"中的潜在客户#define G_SIZE (1 + 1 + 1 + DBL_DECIMAL_DIG-1 + 1 + 1 + 5 + 1) char buf[G_SIZE * 2]; int cnt = snprintf(buf, sizeof buf, "%.*g", DBL_DECIMAL_DIG, value); if (cnt < 0 || cnt >= sizeof buf) { unexpected_conversion_hanlder(); } 是要打印的最小字符。它在这里很少用。

    解决方案:使用慷慨的考虑估计最长的缓冲区 - 然后加倍。

    snprintf()

    或使用可变长度数组和2次调用int cnt = snprintf(NULL, 0, "%.*g", DBL_DECIMAL_DIG, value); char buf[cnt + 1]; snprintf(buf, sizeof buf , "%.*g", DBL_DECIMAL_DIG, value);

    mod_wsgi