我有一个 ascii “15605632.68128593”,我希望将其转换为双精度而不丢失准确性-
so
double d;
d=(double)atof("15605632.68128593");
printf("%f",d);
printed result is 15605632.681286
有任何想法吗 ?
谢谢 - !
我有一个 ascii “15605632.68128593”,我希望将其转换为双精度而不丢失准确性-
so
double d;
d=(double)atof("15605632.68128593");
printf("%f",d);
printed result is 15605632.681286
有任何想法吗 ?
谢谢 - !
您可能没有得到所有尾随小数位。试试printf("%.8f", d)
。
您也可以尝试sscanf("15605632.68128593", "%lf", &d)
代替atof
通话。
也没有必要将结果转换为atof
to double
。已经是双标了。但是演员阵容并没有什么坏处。
请注意 - 至少大约 6 年前,当我详细查看这一点时 - 许多printf
和scanf
实现都是错误的,因为它们没有像你想象的那样完美逆反。Visual C/C++ 和 gcc 在其本机实现中都存在问题。 这篇论文是一个有用的参考。
带有 gcc 4.3.4 的 Cygwin:
#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
目标:将“15605632.68128593”转换为双精度而不损失精度。
atof()
完成了该程序所能做的最好的事情。但由于15605632.68128593
(一个 16 位数字)在您的 中不能完全表示为 a ,因此它近似为。因此失去了准确性,尽管损失很小。double
C
1.560563268128593080...e+07
典型 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
可能就足够了。 细节
该程序用于您的确切"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
double
没有那么精确。它只能从十进制字符串往返 15 ( DBL_DIG
from float.h
) 小数位double
到十进制字符串。
编辑:虽然,总的来说,我的说法是正确的,但这似乎不是你的问题。虽然存在无法往返的 16 位小数位数,但此特定输入可以。