打印sprintf科学记数法中的所有有效数字

时间:2014-10-03 17:24:18

标签: c r printf

当R将科学记数法中的大数字转换为字符串时,它包含所有有效数字而不包含尾随零。是否可以使用sprintf

在C中完成此操作
> as.character(12345e11)
[1] "1.2345e+15"
> as.character(1234500000e6)
[1] "1.2345e+15"
> as.character(1234500001e6)
[1] "1.234500001e+15"

我试过sprintf(buf, "%g", val),但这似乎最多包含5个十进制数字。我还尝试使用sprintf(buf, "%.18g", val)设置更高的精度,但这将包括非有效数字和尾随零。

有没有办法获得sprintf(buf, "%g", val)的行为,但会增加5位数限制?

1 个答案:

答案 0 :(得分:3)

代码可以使用"%.18e""%.18g",但问题是“18”应该有多大? 18是最好的价值吗?答案在于DBL_DECIMAL_DIG

DBL_DECIMAL_DIG是要打印的最小有效位数,以确保double 字符串往返为同一个{ {1}} all double

建议使用格式说明符double

请注意"%.*e"中的“18”是小数点后的有效位数。所以"%.18e"打印19位有效数字。


使用以十六进制输出打印的"%.18e" 对于十进制输出:

printf("%a", x);

参考Printf width specificer to maintain precision of floating-point value


使用典型#include <float.h> // sign + digit + dp + digits + e + sign + expo + \0 char buf[1 + 1 + 1 + (DBL_DECIMAL_DIG - 1) + 1 + 1 + 5 + 1]; sprintf(buf, "%.*e", DBL_DECIMAL_DIG - 1, x); binary64格式的y = 1.0/3.0之类的数字需要查看大约53个十进制数字才能看到其确切的值。但是,成功的往返不需要许多尾随数字。


现在我们知道要打印的大多数数字,使用下面的内容来摆脱那些讨厌的尾随double数字。

0

输出

#include <float.h>
#include <math.h>
#include <stdio.h>
#include <string.h>

char *trim0(double x, char *buf) {
  sprintf(buf, "% .*e", DBL_DECIMAL_DIG - 1, x);
  if (isfinite(x)) {
    char *p = &buf[DBL_DECIMAL_DIG + 1];  // address of last significand digit
    char *t;
    for (t=p; *t == '0'; t--);
    memmove(t+1, p+1, strlen(p+1)+1);
  }
  return buf;
}

int main(void) {
  char buf[1 + 1 + 1 + (DBL_DECIMAL_DIG - 1) + 1 + 1 + 5 + 1];
  printf("%s\n", trim0(1.2, buf));
  printf("%s\n", trim0(1.0/7, buf));
  return 0;
}