当R将科学记数法中的大数字转换为字符串时,它包含所有有效数字而不包括尾随零.是否有可能在C中实现这一点sprintf?
> as.character(12345e11)
[1] "1.2345e+15"
> as.character(1234500000e6)
[1] "1.2345e+15"
> as.character(1234500001e6)
[1] "1.234500001e+15"
Run Code Online (Sandbox Code Playgroud)
我试过sprintf(buf, "%g", val)但这似乎最多包括5位十进制数字.我也尝试设置更高的精度,sprintf(buf, "%.18g", val)但这将包括非有效数字和尾随零.
有没有办法获得行为,sprintf(buf, "%g", val)但增加5位数限制?
代码可以使用"%.18e"or "%.18g",但问题是“18”应该有多大?18是最好的价值吗?答案就在于DBL_DECIMAL_DIG。
DBL_DECIMAL_DIG是要打印的有效数字的最小数量,以确保所有的字符串的往返都完全相同。doubledouble double
推荐使用格式说明符"%.*e"。
注意,其中的“18”是小数点后"%.18e"的有效位数。因此打印 19 位有效数字。"%.18e"
使用printf("%a", x);which 以十六进制输出进行打印。
对于十进制输出:
#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);
Run Code Online (Sandbox Code Playgroud)
y = 1.0/3.0像使用典型的double binary64格式这样的数字需要查看大约 53 位十进制数字才能看到其准确值。但成功的往返并不需要许多尾随数字。
现在我们知道要打印的最多数字,请使用以下内容来摆脱那些讨厌的尾随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;
}
Run Code Online (Sandbox Code Playgroud)
输出
1.2e+00
1.4285714285714285e-01
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3430 次 |
| 最近记录: |