【问题标题】:Why 0.1 represented in float correctly? (I know why not in result of 2.0-1.9)为什么 0.1 正确地以浮点数表示? (我知道为什么不是 2.0-1.9 的结果)
【发布时间】:2012-08-26 08:53:41
【问题描述】:

我最近阅读了很多关于浮点表示的内容(包括:How To Represent 0.1 In Floating Point Arithmetic And Decimal)。 现在我明白 0.1 无法正确表示,当我这样做时:

System.out.println(2.0f - 1.9f);

我永远不会得到精确的结果。

所以问题是: 为了正确打印 0.1,如何在以下代码中表示 0.1f? 那是某种合成糖吗? 在我上面提到的文章中说:0.1 在内存中表示为 0.100000001490116119384765625。那么为什么我没有得到这段代码的输出:

System.out.println(0.1f);

Java 是如何处理这个问题的?

【问题讨论】:

  • 第二个输出有多少位有效数字?

标签: java floating-point


【解决方案1】:

System.out.println 对浮点数和双精度数进行一些舍入。它使用 Float.toString(),它本身(在 oraclew JDK 中)委托给 FloatingDecimal 类 - 您可以查看 the source of FloatingDecimal#toJavaFormatString() 了解详细信息。

如果你尝试:

BigDecimal bd = new BigDecimal(0.1f);
System.out.println(bd);

您将看到 0.1f 的实际值:0.100000001490116119384765625。

【讨论】:

  • 哇,好快的速度!非常感谢!
  • 您根本不需要查看源代码 - 您只需查看 Float.toString(float) 的文档即可,这非常清楚地说明了 Float.toString(0.1f) 将返回“0.1”的原因。跨度>
  • @JonSkeet 我的意思是他可以查看源代码以了解它是如何完成的,而不是为什么 - 您在回答中解决了原因。
  • 但表达式在传递给 System.println 之前会被计算。如果有不同的结果,那只能是因为表达式解析为不同的值。那么为什么表达式2.0f - 1.9f 的结果与表达式0.1f 有某种不同呢?
  • @Michael 因为2.0f - 1.9f != 0.1f。在此处查看它们的确切值:ideone.com/VCR3wJ
【解决方案2】:

来自Float.toString(float) 的文档(其结果总是与您打印的字符串相同):

m 或 a 的小数部分必须打印多少位?必须至少有一个数字来表示小数部分,除此之外,必须有尽可能多的数字,但仅能将参数值与浮点类型的相邻值唯一区分开来。

由于 0.1f 是最接近精确值 0.1 的可表示浮点数,因此无需更多数字即可将其与 float 类型的任何其他值唯一区分开来。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-08
  • 2019-12-16
  • 2019-08-21
  • 1970-01-01
相关资源
最近更新 更多