提问人:Abdulmalek Almkainzi 提问时间:9/25/2023 最后编辑:Abdulmalek Almkainzi 更新时间:9/25/2023 访问量:122
%g 浮点数表示的最大字符串长度是多少?
What is the maximum string length for %g float representation?
问:
堆栈分配的字符串需要多大才能以 %g 格式存储任何浮点数/双精度?
int main()
{
float f;
double d;
char f_str[ ?? ];
char d_str[ ?? ];
sprintf(f_str, "%g", f);
sprintf(d_str, "%lg", d);
}
编辑:
我希望在编译时知道字符串大小,这样我就不依赖于堆分配或 VLA
答:
您可以使用 snprintf() 来计算特定格式字符串和值所需的确切长度
float f = 3.14159265358979;
int f_len = snprintf(NULL, 0, "%g", f);
char f_str[f_len + 1]; // or malloc...
sprintf(f_str, "%g", f); // it fits
// remember to free if you malloc'd before
评论
f_len
f_str
%g 浮点数表示的最大字符串长度是多少?
当值在 10+/- 999 以内时为 13
15 与二进制128
对于极值,使用指数表示法。"%g"
"%g"
,缺少宽度或精度,将打印 6 位有效数字。
长期预期形式:
[sign][digit].[5 digits]e[sign][expo_digits]
1 1 1 5 1 1 3 --> 13
例:
// 1234567890123
DBL_TRUE_MIN -4.94066e-324
当具有更宽的指数范围时,需要额外的空间。
double
NAN 可能会打印更长的内容。很多都是实现定义的。一个合理的最坏情况形式会将其估计为“-sNAN”十进制有效载荷“ binary64 的有效载荷可能是小数点后 16 位。
堆栈分配的字符串需要多大才能以 %g 格式存储任何浮点数/双精度?
如果寻求一个常数,给定指数范围(以十进制表示)可能超过 3 位,并且 NAN 可能会打印有效负载,我会在 NAN 有效负载打印上进行缩放,因为这肯定是最坏的情况。使用以位为单位的有效大小,通过按 log10(2) 缩放来确定十进制有效负载。
#define DBL_SIZE (sizeof(double)*CHAR_BIT)
#define LOG10_2_NUM 302
#define LOG10_2_DEN 1000
#define DBL_PAYLOAD (DBL_MANT_DIG*LOG10_2_NUM/LOG10_2_DEN)
#define DBL_G_SIZE (5 /* -sNAN */ + DBL_PAYLOAD + 1 /* \0 */ )
因此,对于普通 .double
鉴于所有潜在的实现定义属性,我会使用 .snprintf()
char buf[DBL_G_SIZE];
int len = snprintf(buf, sizeof buf, "%g", x);
assert(len > 0 && (unsigned) len < sizeof buf);
评论
#define DBL_PAYLOAD (DBL_MANT_DIG*LOG10_2_NUM/LOG10_2_DEN)
... DBL_MANT_DIG*LOG10_2_NUM/LOG10_2_DEN + 1)
%g
char buf[DBL_G_SIZE * 2];
这取决于实际的浮点格式和当前区域设置,因为某些字符(如小数点字符)可能需要几个字节。例如,如果对应于 IEEE 754 binary64 格式(又名双精度),则在 C 语言环境中,最大字符串长度(以字节数表示)为 13,但实际上可能是 14(我什至不认为 C 标准有限制)。double
例:
#include <stdio.h>
#include <float.h>
#include <string.h>
#include <locale.h>
static void f (void)
{
char s[256];
double x = -DBL_MAX;
printf ("%g\n", x);
sprintf (s, "%g", x);
printf ("%zu\n", strlen (s));
}
int main (void)
{
f ();
setlocale (LC_ALL, "ps_AF");
f ();
return 0;
}
在我的 Debian Linux 机器上(其中启用了所有语言环境),我得到:
-1.79769e+308
13
-1٫79769e+308
14
14 是由于 U+066B 阿拉伯十进制分隔符用于ps_AF区域设置(基于 UTF-8)中的小数点字符,编码为 D9 AB。
答案与 类似,但您需要知道相关格式的最小和最大指数。long double
评论
-1e+5
-FLT_MAX
-DBL_MAX
-LDBL_MAX
-3.40282e+38
-1.79769e+308
-1.18973e+4932
%g