mar*_*tin 49 c c++ floating-point
当我将无符号的8位int转换为字符串时,我知道结果总是最多3个字符(对于255),对于有符号的8位int,我们需要4个字符,例如"-128".
现在我真正想知道的是浮点值是一回事.将任何"double"或"float"值表示为字符串所需的最大字符数是多少?
假设一个常规的C/C++ double(IEEE 754)和正常的十进制扩展(即没有%e printf格式化).
我甚至不确定真正的小数字(即0.234234)是否会比真正庞大的数字(代表整数的双数)更长?
Mik*_*our 34
<float.h>C或<cfloat>C++中的标准头包含几个常量,用于处理浮点类型的范围和其他度量.其中之一是DBL_MAX_10_EXP表示所有double值所需的最大10次幂指数.由于1eN需要N+1数字来表示,并且可能还有负号,所以答案是
int max_digits = DBL_MAX_10_EXP + 2;
Run Code Online (Sandbox Code Playgroud)
这假设指数大于表示最大可能尾数值所需的位数; 否则,还会有一个小数点后跟更多数字.
更正
最长的数字实际上是最小的可表示的负数:它需要足够的数字来覆盖指数和尾数.这个值是-pow(2, DBL_MIN_EXP - DBL_MANT_DIG),其中DBL_MIN_EXP是负数.很容易看到(并通过归纳证明)-pow(2,-N)需要3+N非科学十进制表示"-0."的N字符(后跟数字).所以答案是
int max_digits = 3 + DBL_MANT_DIG - DBL_MIN_EXP
Run Code Online (Sandbox Code Playgroud)
对于64位IEEE双核,我们有
DBL_MANT_DIG = 53
DBL_MIN_EXP = -1023
max_digits = 3 + 53 - (-1023) = 1079
Run Code Online (Sandbox Code Playgroud)
Vit*_*kov 15
根据IEEE 754-1985,由double类型表示的值的最长表示法,即:
-2.2250738585072020E-308
有24个字符.
小智 6
比IEEE-754 规范更详细的正确信息来源是加州大学伯克利分校第 4 页的这些讲义,以及一些 DIY 计算。这些讲座幻灯片也适合工程专业的学生。
| Single| Double | Extended | Quad |
|:-----:|:------:|:--------:|:-----:|
| 16 | 24 | 30 | 45 |
Run Code Online (Sandbox Code Playgroud)
这些数字基于以下计算:
| Single| Double | Extended | Quad |
|:-----:|:------:|:--------:|:-----:|
| 9 | 17 | 21 | 36 |
* Quantities listed in decimals.
Run Code Online (Sandbox Code Playgroud)
小数计数基于以下公式:至多 Ceiling(1 + N Log_10(2)) 小数,其中 N 是整数部分中的位数*。
| Single| Double | Extended | Quad |
|:-----:|:------:|:--------:|:-----:|
| 5 | 5 | 7 | 7 |
* Standard format is `e-123`.
Run Code Online (Sandbox Code Playgroud)
打印浮点数的最快算法是研究论文“快速准确地打印浮点数”中详述的 Grisu2 算法。我能找到的最好的基准可以在这里找到。
您可以用来snprintf()检查您需要多少个字符。
snprintf()返回打印传递给它的任何内容所需的字符数。
/* NOT TESTED */
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char dummy[1];
double value = 42.000042; /* or anything else */
int siz;
char *representation;
siz = snprintf(dummy, sizeof dummy, "%f", value);
printf("exact length needed to represent 'value' "
"(without the '\\0' terminator) is %d.\n", siz);
representation = malloc(siz + 1);
if (representation) {
sprintf(representation, "%f", value);
/* use `representation` */
free(representation);
} else {
/* no memory */
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
注:snprintf()是C99函数。如果 C89 编译器将其作为扩展提供,它可能不会执行上述程序所期望的操作。
编辑:将链接更改为snprintf()实际描述 C99 标准强加的功能的链接;原始链接中的描述是错误的。
2013:将链接更改回POSIX 站点,与第一次编辑的站点相比,我更喜欢该站点。