【问题标题】:Printing out double precision numbers identical to original decimal number打印出与原始十进制数相同的双精度数
【发布时间】:2015-11-15 06:49:49
【问题描述】:

我希望能够打印出一个双精度数,它与 C 语言中的原始十进制数相同。

char buf[1000];
double d = ______;

如果是双份的话,我愿意

snprintf(buf, sizeof(buf), "%.17g", .1);

但它会打印出来:printf("%s", buf);

0.10000000000000001

最后一个1 是舍入错误

如果您尝试表示 .1,它会打印出最接近的十进制表示双精度值。将.1 转换为加倍,会出现舍入错误。转换回十进制,你会得到另一个四舍五入的错误。

有没有办法解决这个问题?

【问题讨论】:

  • 有点不清楚您是在询问 IEEE-754 双精度浮点格式 的限制,还是在询问如何解决它。请澄清。
  • @DavidC.Rankin 您能否解释一下 IEEE-754 双精度浮点格式的限制以及如何解决上述问题。我很想知道
  • @psyco 限制具有误导性。二进制表示意味着许多具有精确十进制表示的值无法准确表示。但是,这是设计使然,二进制浮点具有许多优点。对于它的预期用途,我认为不可能有更好的设计。
  • @psyco 是另一个 David 和 Jens,并且已经解释得更加雄辩了。我唯一要补充的是,您面临的问题是由于可用于描述所有可能的浮点值的位数有限。 IEEE-754 双精度格式使用 1 位符号位,11 位用于指数,在 64 位中仅留下 52 位用于余数,称为尾数或有效位。根本没有足够的位来准确地唯一描述所有可能的浮点值。

标签: c precision


【解决方案1】:

对此的“标准”解决方案并不漂亮:对所有浮点常量使用十六进制表示法,而不是十进制。不幸的是,它们看起来像 0x1.7aP-13 人类难以消化的东西。但是有了它们,您就可以保证写出和读回给您带来完全相同的价值。

标准 C 库 strtodprintf(格式为 %a)和类似工具支持此功能,前提是您的 C 库至少实现了 C99。使用它时必须注意的一个小问题是printf 的小数点依赖于locale。因此,如果您的语言环境具有例如 ,,您必须确保使用相同的 locale 进行读写。

【讨论】:

    【解决方案2】:

    一般来说,您尝试做的事情是不可能的。浮点值使用二进制表示,许多具有终止十进制表示的值没有精确的二进制表示。

    从根本上说,如果您希望保留十进制表示,那么您应该使用将该值表示为十进制的数据类型。

    可能值得指出 Python 用于显示浮点值的方法。 Python 显示最短的十进制表示,其最近的浮点值是显示的值。

    0.1 为例,该值不能以二进制浮点数精确表示。所以使用最接近的浮点值。当您请求该二进制值的十进制表示时,Python 运行时确定 0.1 是最短的表示,例如 float('0.1') == value

    如果这种方法对您有用,那么您应该研究一下:https://bugs.python.org/issue1580

    【讨论】:

      猜你喜欢
      • 2020-10-13
      • 1970-01-01
      • 2013-05-02
      • 2011-02-14
      • 1970-01-01
      • 2014-02-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多