简体   繁体   English

正确的方法来将双精度型转换为字符串而不分配比所需的更多内存?

[英]Proper way to convert a double to string without allocating more memory than required?

I'm wondering what the proper way is too convert a double of unknown value size to a string without allocating too much memory. 我想知道什么合适的方法也可以将未知值 大小 的双精度转换为字符串而不分配太多内存。 Is there any way to figure out the count of digits in a double? 有什么办法可以计算出双数位数吗? I don't want to allocate too much or too less memory. 我不想分配太多或更少的内存。

You can use NULL as the first argument of snprintf to get the size: 您可以使用NULL作为snprintf的第一个参数来获取大小:

C99 allows str to be NULL and gives the return value (as always) as the number of characters that would have been written in case the output string has been large enough. C99允许str为NULL,并提供返回值(一如既往),以防万一输出字符串足够大时将要写入的字符数。

And then malloc : 然后malloc

int main(void)
{
    double num = 3.14;
    size_t len;
    char *str;

    len = (size_t)snprintf(NULL, 0, "%f", num) + 1;
    str = malloc(len);
    snprintf(str, len, "%f", num);
    puts(str);
    free(str);
    return 0;
}

Here you have a basic example of how to use snprintf when you only want to know the length of the representation: 在这里,您有一个基本示例,该示例仅在想知道表示形式的长度时如何使用snprintf

#include <stdio.h>
#include <math.h>
#include <stdlib.h>

int main(void)
{
    int size = snprintf(NULL, 0, "%.15lf", M_PI);
    char *pi = malloc(size + 1);
    sprintf(pi, "%.15lf", M_PI);

    printf("PI: '%s'\n", pi);

    free(pi);
    return 0;
}

Proper way to convert a double to string without allocating more memory than required? 正确的方法来将双精度型转换为字符串而不分配比所需的更多内存?

Use snprintf() to determine the character count need. 使用snprintf()确定需要的字符数。

double value = foo();
int size = snprintf(NULL, 0, some_format, value);
if (size < 0) Handle_encoding_error(); // This is very rare
else {
  char *buffer = malloc(size + 1u);
  if (buffer == NULL) Handle_OOM_error(); // This is also rare
  else {
    snprintf(buffer, 0, some_format, value);
    puts(buffer);
    free(buffer); 
  }
}

What format to use depends on coding goals. 使用哪种格式取决于编码目标。 "%f" often results in many uninformative digits for large values and "0.00000" for about half of all double as many are wee values less than 0.0000005 in magnitude. "%f"结果往往较大值许多无信息的数字和"0.00000"的一半左右的double因为许多小于幅度0.0000005凌晨值。

A good way to print a double with significant digits employ exponential notation. 打印带有有效数字的double精度字的一种好方法是采用指数表示法。 What is great about using exponential notation is not only is the double fully expressed, it maximum string size need can be pre-calculated (about 28) and is not excessive. 使用指数表示法的最大好处是不仅可以完全表示double精度数,而且可以预先计算最大字符串大小需求(大约28),而且不会过多。

By printing with exponential notation and precision of DBL_DECIMAL_DIG - 1 , code does not need more digits to "round-trip" the string back to the same double with strtod() or sscanf() . 通过使用指数表示法和精度DBL_DECIMAL_DIG - 1代码,代码不需要更多的数字即可使用strtod()sscanf()将字符串“回程”回相同的double 精度数。

"%a"    // Hexadecimal signicand
"%.*e"  // Decimal

int size = snprintf(NULL, 0, "%a", value);
// or 
int size = snprintf(NULL, 0, "%.*e", DBL_DECIMAL_DIG-1, value);

// or directly with minimal extra space
//         -   d   .    dddddd                 e   -  expo \0
#define N (1 + 1 + 1 + (DBL_DECIMAL_DIG - 1) + 1 + 1 + 6 + 1)
char buf[N]; 
snprintf(buf, sizeof buf, "%.*e", DBL_DECIMAL_DIG-1, value);

See Printf width specifier to maintain precision of floating-point value 请参阅Printf宽度说明符以保持浮点值的精度

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM