我正在维护一个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")。然而,浮点数的问题可能非常违反直觉,我不确定我是否错过了某些东西。我的推理是否正确?
答案 0 :(得分:3)
继续发表评论,
%1.
('.'
之前的一个)指定最小字段宽度,它对可出现的位数没有限制。如果数字位数表示字段宽度,则字段将展开。
对于g
或G
转换说明符,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
这可能会更长?
double
可能需要更多17位数来区分所有DBL_DECIMAL_DIG
。 (可以double
检测到)1
添加额外字符(不太可能) "%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