将浮点数转换为double而不会丢失精度

我有一个原始的浮动,我需要作为一个原始的双。 简单地将浮点数转换为double值给我奇怪的额外精度。 例如:

float temp = 14009.35F; System.out.println(Float.toString(temp)); // Prints 14009.35 System.out.println(Double.toString((double)temp)); // Prints 14009.349609375 

然而,如果不是投射,我输出一个string的浮动,并parsingstring为双,我得到我想要的:

 System.out.println(Double.toString(Double.parseDouble(Float.toString(temp)))); // Prints 14009.35 

有没有更好的方法比去串和回?

这并不是说你实际上得到了更高的精度 – 这是浮点数不能准确地表示你原来想要的数字。 双精确地表示原始的浮标; toString显示已经存在的“额外”数据。

例如(这些数字是不对的,我只是在做)支持你有:

 float f = 0.1F; double d = f; 

那么f的值可能恰好是0.100000234523。 d将具有完全相同的值,但是当您将其转换为string时,它会“相信”精确到更高的精度,因此不会太早完成,您将看到“额外数字”已经在那里,但对你隐藏。

当你转换成一个string并返回时,最后会得到一个比原来的float值更接近string值的double值 – 但是如果你真的相信string的值是你真正想要的值,那就是好的。

你确定float / double是适合的types而不是BigDecimal吗? 如果您要使用具有精确小数值(例如金钱)的数字,那么BigDecimal是更适合的typesIMO。

我发现转换到二进制表示更容易把握这个问题。

 float f = 0.27f; double d2 = (double) f; double d3 = 0.27d; System.out.println(Integer.toBinaryString(Float.floatToRawIntBits(f))); System.out.println(Long.toBinaryString(Double.doubleToRawLongBits(d2))); System.out.println(Long.toBinaryString(Double.doubleToRawLongBits(d3))); 

你可以看到float被扩展为double,通过在最后加上0,但是0.27的双重表示“更准确”,因此是问题所在。

  111110100010100011110101110001 11111111010001010001111010111000100000000000000000000000000000 11111111010001010001111010111000010100011110101110000101001000 

这是由于Float.toString(float)的合同,部分地说:

小数部分必须打印多less位数? 必须至less有一位数字才能表示小数部分,并且除此之外还必须有尽可能多的数字,以便唯一地区分参数值和types为float的相邻值。 也就是说,假设x是由这种方法产生的十进制表示的精确math值,用于有限非零参数f。 那么f必须是最靠近x的浮点值; 或者,如果两个浮点数值都等于x,则f必须是其中的一个,而f的有效数的最低有效位必须为0。

我今天遇到这个问题,不能使用重构到BigDecimal,因为这个项目真的很大。 但是我发现解决scheme使用

 Float result = new Float(5623.23) Double doubleResult = new FloatingDecimal(result.floatValue()).doubleValue() 

这工作。

请注意,调用result.doubleValue()返回5623.22998046875

但是调用doubleResult.doubleValue()会正确返回5623.23

但是我不完全确定它是否是一个正确的解决scheme。

使用BigDecimal而不是float / double 。 有很多数字不能表示为二进制浮点数(例如0.1 )。 因此,您必须始终将结果四舍五入到已知的精度或使用BigDecimal

有关更多信息,请参见http://en.wikipedia.org/wiki/Floating_point

我发现了以下解决scheme:

 public static Double getFloatAsDouble(Float fValue) { return Double.valueOf(fValue.toString()); } 

如果你使用floatdouble来代替FloatDouble,使用下面的代码:

 public static double getFloatAsDouble(float value) { return Double.valueOf(Float.valueOf(value).toString()).doubleValue(); } 

这是否工作?

 float flt = 145.664454; Double dbl = 0.0; dbl += flt; 

浮动本质上是不精确的,总是有整齐的“问题”。 如果精度很重要,那么可以考虑重构应用程序以使用Decimal或BigDecimal。

是的,由于处理器支持,浮点运算速度比小数快。 但是,你想快速还是准确?

有关信息,请参阅第48条 – 在需要精确值时避免float和double,Joshua Bloch撰写的Effective Java第2版。 这本书塞满了好东西,绝对值得一看。