java - Java 如何往返 String -> float -> String 甚至对于(某些)不能表示为 float 的值?

标签 java math floating-point numbers type-conversion

<分区>

正如在许多地方(例如 Why can't decimal numbers be represented exactly in binary? )所解释的那样,并非所有小数都可以表示为浮点值(例如存储在 Java 中的 float 中)。

给出的典型例子是“0.2”。根据这个漂亮的IEEE 754 Converter ,最接近 0.2 的 float 大约为 0.20000000298023224 ,因此将“0.2”解析为 float 应该会产生此结果。

但是,我注意到 Java 似乎能够完成不可能的事情:

String number="0.2";
float f = Float.parseFloat(number);
System.out.println("Result of roundtrip String -> float -> String: "+f);

打印:

Result of roundtrip String -> float -> String: 0.2

Test on IDeone.com

Java 如何知道我想要(四舍五入的)输出“0.2”,而不是上面解释的精确输出“0.20000000298023224”?

Javadocs of Float.toString()试着解释一下:

How many digits must be printed for the fractional part of m or a? There must be at least one digit to represent the fractional part, and beyond that as many, but only as many, more digits as are needed to uniquely distinguish the argument value from adjacent values of type float.

不幸的是,这让我更加困惑。为什么“根据需要打印尽可能多的数字以唯一区分参数值”允许 Java 打印“0.2”?

理想情况下,答案还可以解释为什么选择这种打印算法。是为了让(一些)往返工作,就像这个例子一样?还有别的动机吗?

最佳答案

输出的四舍五入不是因为某些打印算法。这是因为 float 的大小。如果你这样做:

String fs = "0.2";
double f = Float.parseFloat(fs);
System.out.println(f);

你得到:

0.20000000298023224

Test on Ideone.com

这清楚地表明字符串“0.2”被解析为 0.20000000298023224,但 float 数据类型无法容纳它,并将其四舍五入为 0.2。 double 数据类型能够保存此数据,因此,当您将其解析为 float,但将其存储为 double 时,您会得到预期的输出。

关于java - Java 如何往返 String -> float -> String 甚至对于(某些)不能表示为 float 的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38013662/

相关文章:

math - float 学坏了吗?

c++ - 使用 float 的系列总和

java - 链表迭代器内部类-java

java - 对java中的线程感到困惑

c - C 中的莱布尼茨函数

ios - 为什么括号会在 objective-c 中搞乱这个数学?

算法最优填充

java - Apache ServiceMix 安装 bundle OSGI

Java 禁用 OSX 强制退出

bash - 如何在 bash/batch 脚本中递减浮点变量