【问题标题】:sprintf formatting of double value双值的sprintf格式
【发布时间】:2012-04-26 06:16:24
【问题描述】:

在 UNIX 中使用 sprintf()double 值转换为字符串时遇到一个特定问题。

例如我有两个值:

double a = 0.009984354523452;
double b = 0.01;

在转换时,我正在使用:

sprintf(somestringvar, "Double value : %.15f \n", a);
sprintf(diffstringvar, "Double value : %.15f \n", b);

转换为字符串。

我的问题是'a',该值打印正确,但对于'b'的值,0 被附加在尾端。请提供任何将“a”和“b”表示为精确值的常用方法。

【问题讨论】:

  • 我会用 std::ostringstream 来做这种事情。
  • 一般情况下,不要使用sprintf(),因为它会导致缓冲区溢出。请改用snprintf(),或Microsoft 在Windows 上提供的_s“安全”版本之一。 p.s.欢迎使用 Stack Overflow!
  • 您好,感谢您的早期回复。 ostringstream 没有完全精确。一个值仅打印为 0.009976。我可以使用 snprintf() 但问题在于正确打印值。
  • 您必须注意的另一件事:通常,浮点数不能精确表示,因为尾数只有有限的长度。例如。 printf("1/10 = %.50f\n", 0.1); 在我的机器上输出以下内容:d = 0.10000000000000000555111512312578270211815834045410。您可能想阅读floating point representation
  • 这是很有价值的信息。确实,浮点数不能准确表示,但我只是试图打印特定双变量中存在的值。我实际上是从数据库访问数据,在这种情况下,我必须准确地向用户打印数据库中的任何内容。但不是通过“规范化”或“截断”或“在尾部附加零”。通过使用 %g 或 %f 或 ostringstream,如果我使用 %.20f 大值可以正常化和截断值(如 0.009984354523452 为 0.009984),但小的值如 0.01 为 0.0100 ..... 18 个零

标签: c++ c unix printf


【解决方案1】:

打印 b 时得到零,因为您告诉 printf 打印小数点后 15 位 (%.15f),它很乖巧地这样做了。要获得“准确”的信息,您可能会通过简单的%g 获得更好的运气。


[根据最近的 cmets 更新]

事情真的取决于你所说的“准确”是什么意思。如果确切地说,您的意思是“用户最初输入的内容”,那么双精度可能不是您的最佳选择。也许将值存储为字符串,然后在需要在计算中使用它时将其转换为双精度值可能会起作用。一旦基于文本的十进制数转换为双精度数,它通常不再与文本完全相同。虽然printf()ostream 会尽职尽责地打印出 double 所持有的内容(有时它会很幸运,并且它打印的内容看起来与原始值相同),但问题是 double 本身不再持有实际的原始值。事实上它从来没有。

或者,您可能更喜欢精确的数字实现,而不是像双精度数这样的固有近似值。例如,MySQL 有 NUMERIC and DECIMAL 类型支持完美的精度,但代价是强制您提前指定整数和小数位数。这称为arbitrary precision arithmetic,并且有一些库可以在 C/C++ 中执行此操作。

【讨论】:

  • 感谢您的回复,我可以理解添加 zeoes 的逻辑部分。但问题是在运行时我应该从数据库中读取值。值可以是如上所示的任何类型,因此我正在寻找打印精确值的一般方法。我尝试了 '%g',即使它正在将值 'a' 标准化为 0.009976
  • 为什么人们一直投反对票?如果有问题,请说出来,以便我改进或提供您自己的替代答案。
猜你喜欢
  • 1970-01-01
  • 2014-01-30
  • 1970-01-01
  • 1970-01-01
  • 2015-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多