我有一个ascii“15605632.68128593”,我希望转换 在没有失去准确的情况下达到双倍 -
so
double d;
d=(double)atof("15605632.68128593");
printf("%f",d);
printed result is 15605632.681286
有什么想法吗?
谢谢 - !
答案 0 :(得分:8)
很可能你没有得到所有尾随小数位。试试printf("%.8f", d)
。
您也可以尝试sscanf("15605632.68128593", "%lf", &d)
代替atof
来电。
也没有必要将atof
的结果转换为double
。它已经是一个双倍。但演员没有伤害。
请注意 - 至少大约6年前,当我仔细研究这个问题时 - 许多printf
和scanf
实施都是错误的,因为它们不像你那样完美地反转。假设。 Visual C / C ++和gcc在其本机实现中都存在问题。 This paper是一个有用的参考。
Cygwin与gcc 4.3.4:
#include <stdio.h>
int main(void)
{
double x;
sscanf("15605632.68128593", "%lf", &x);
printf("%.8f\n", x);
return 0;
}
然后:
# gcc foo.c
# ./a
15605632.68128593
答案 1 :(得分:3)
目标:将“15605632.68128593”转换为双精度而不会失去准确性。
atof()
完成了程序可以做到的最好。但由于15605632.68128593
(一个16位数字)在double
中完全无法表示为C
,因此它近似为1.560563268128593080...e+07
。因此,虽然损失很小,但准确性已经丧失。
Typical double
可代表约2 64 个不同的数字。附近的候选人和OP的字符串如下所示,以供参考。
15605632.68128592893... previous double
"15605632.68128593"
15605632.68128593080... closest double
在尝试打印时出现了悲痛,认为打印的内容是x
的完全值。而是打印了一个舍入值。使用%f
说明符默认为'。'右侧的6个位置。提供报告的15605632.681286
,一个14位数字。
查看所有double
的所有有效数字的更好方法是将%e
格式与DBL_DIG
一起使用。 DBL_DIG
是'。'右边的最多位数,在十进制指数表示法 %e
中,以显示“往返”a所需的所有数字double
(字符串加倍到字符串,没有字符串差异)。由于%e
始终在“。”左侧显示1位数字,因此下方的图片会显示1 + DBL_DIG
个有效数字。 DBL_DIG
在我的我和许多C
环境中都是15,但它有所不同。
如果您希望显示所有有效数字,则需要确定重要的内容。 nextafter()
函数显示下一个可表示的double
。所以我们可能想要显示至少足够的数字来区分x和下一个x。我推荐DBL_DIG + 2
。虽然DBL_DIG
可能就足够了。 Details
程序用于"1.560563268128593e+07"
的完全值为15605632.68128593079745769500732421875
。在某些情况下,您需要查看所有这些数字。即使您要求大量数字,在某些时候,printf()
只会给你零。
#include <stdio.h>
#include <float.h>
#include <tgmath.h>
int main(int argc, char *argv[]) {
double x;
x = atof("15605632.68128593");
printf("%.*le\n",DBL_DIG, x); // All digits "round-trip" string-to-double-string w/o loss
printf("%.*le\n",DBL_DIG + 1, x); // All the significant digit "one-way" double-string
printf("%.*le\n",DBL_DIG + 1, nextafter(x, 2*x)); // The next representable double
printf("%.*le\n",DBL_DIG + 3, x); // What happens with a few more
printf("%.*le\n",DBL_DIG + 30, x); // What happens if you are a bit loony
return 0;
}
1.560563268128593e+07
1.5605632681285931e+07
1.5605632681285933e+07
1.560563268128593080e+07
1.560563268128593079745769500732421875000000000e+07
答案 2 :(得分:1)
double
没那么精确。它只能将十进制字符串中的15(DBL_DIG
从float.h
)往返到double
回到十进制字符串。
编辑虽然一般来说,我的说法属实,但这似乎不是你的问题。虽然存在16位小数不能往返的数字,但这个特定的输入可以。