代码可以使用"%.18e"
或"%.18g"
,但问题是“18”应该有多大? 18是最好的价值吗?答案在于DBL_DECIMAL_DIG
。
DBL_DECIMAL_DIG
是显著的最小位数打印到保证的double
到串的往返到完全相同的double
为所有double
。
使用格式说明符"%.*e"
推荐。
请注意,"%.18e"
中的“18”是之后的有效位数小数点后的位数。所以"%.18e"
打印19位有效数字。
使用printf("%a", x);
打印在十六进制输出。
对于小数输出:
#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);
Printf width specificer to maintain precision of floating-point value价
使用典型double
binary64格式需要看到约53个十进制数字来查看其确切值的数字像y = 1.0/3.0
。但是,成功的往返不需要许多尾随数字。
现在我们知道了最数字打印,使用下面摆脱那些烦人的拖尾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;
}
输出
1.2e+00
1.4285714285714285e-01
尾随零实际上是非常显著。 – 5gon12eder 2014-10-03 17:57:40
我不认为这是可能的,至少根据[这](https://stackoverflow.com/questions/277772/avoid-trailing-zeroes-in-printf)后,你可能是重复的。让我感到不安的是''printf''的man页面对'%g'格式表示:*“结果的小数部分除去了尾部零”*我无法观察到这种记录的行为。 – 5gon12eder 2014-10-03 18:10:25
@ 5gon12eder - 如“n = 58.375”这样的精心编制的数字如何?用'printf(“%。18g \ n”,n)'给我'58打印。375',而'n = 58.374'的结果是'58.3740000000000023'注意.375等于3/8,所以它具有精确的浮点表示。大多数任意选择的小数部分不会**具有精确的浮点表示。因此,'%g'不符合您对这些数字的期望。 – user3386109 2014-10-03 18:48:13