3

我有一个 ascii “15605632.68128593”,我希望将其转换为双精度而不丢失准确性-

 so 
 double d;
 d=(double)atof("15605632.68128593");
 printf("%f",d);

 printed result is 15605632.681286

有任何想法吗 ?

谢谢 - !

4

3 回答 3

7

您可能没有得到所有尾随小数位。试试printf("%.8f", d)

您也可以尝试sscanf("15605632.68128593", "%lf", &d)代替atof通话。

也没有必要将结果转换为atofto double。已经是双标了。但是演员阵容并没有什么坏处。

请注意 - 至少大约 6 年前,当我详细查看这一点时 - 许多printfscanf实现都是错误的,因为它们没有像你想象的那样完美逆反。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
于 2013-06-13T01:39:48.947 回答
4

目标:将“15605632.68128593”转换为双精度而不损失精度

atof()完成了该程序所能做的最好的事情。但由于15605632.68128593(一个 16 位数字)在您的 中不能完全表示为 a ,因此它近似为。因此失去了准确性,尽管损失很小。doubleC1.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
于 2013-06-13T07:40:24.813 回答
1

double没有那么精确。它只能从十进制字符串往返 15 ( DBL_DIGfrom float.h) 小数位double到十进制字符串。

编辑:虽然,总的来说,我的说法是正确的,但这似乎不是你的问题。虽然存在无法往返的 16 位小数位数,但此特定输入可以。

于 2013-06-13T02:09:35.600 回答