将 float 转换为 double 且不损失精度
-
06-09-2019 - |
题
我有一个原始的浮点数,我需要一个原始的双精度浮点数。简单地将浮点数转换为 double 会给我带来奇怪的额外精度。例如:
float temp = 14009.35F;
System.out.println(Float.toString(temp)); // Prints 14009.35
System.out.println(Double.toString((double)temp)); // Prints 14009.349609375
但是,如果我不进行强制转换,而是将浮点数输出为字符串,并将该字符串解析为双精度数,我会得到我想要的:
System.out.println(Double.toString(Double.parseDouble(Float.toString(temp))));
// Prints 14009.35
有没有比往返 String 更好的方法?
解决方案
这不是你的真正的获得额外的精度 - 这是浮子没有准确地代表你瞄准了原本数量。双是准确表示原始浮子; toString
是示出“额外”的数据,其已存在。
例如(这些数字是不正确的,我只是胡编)假设你有:
float f = 0.1F;
double d = f;
然后f
的值可能正是0.100000234523。 d
将有完全一样的价值,但是当你将它转换为字符串,将“信任”,它是精确到一个更高的精度,所以不会四舍五入早,你会看到这是“额外数字”已经存在,但是从你隐藏的。
当您转换为字符串和背部,你和一个双值更接近字符串值比原来的浮动是结束了 - 但这只是良好的如果的你真的相信该字符串值是什么,你真正想要的。
您确定浮点/双精度是合适的类型在这里使用的,而不是BigDecimal
?如果你想使用具有精确的十进制值(例如钱)的数字,然后BigDecimal
是一个比较合适类型IMO。
其他提示
我找到转换为二进制表示更容易抓住这个问题。
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)));
可以看到浮子被扩展到双通过加入0到结束,但0.27双表示是“更精确”的,因此该问题。
111110100010100011110101110001
11111111010001010001111010111000100000000000000000000000000000
11111111010001010001111010111000010100011110101110000101001000
这是由于合同 Float.toString(float)
, 其中部分内容是:
必须打印几位数字[…]?必须至少有一个数字来代表小部分,除此之外, 但只有那么多, 需要更多的数字,以唯一将参数值与类型浮子的相邻值区分开。 也就是说,假设x是该方法为有限的非零参数f所产生的十进制表示所示的确切数学值。然后f必须是最接近x的浮子值;或者,如果两个浮点值同样接近x,则F必须是其中之一,而F的最小显着位必须为0。
我遇到这个问题今天不能使用重构为BigDecimal的,因为这个项目确实是巨大的。然而,我发现溶液中使用
Float result = new Float(5623.23)
Double doubleResult = new FloatingDecimal(result.floatValue()).doubleValue()
和其工作原理。
请注意,调用result.doubleValue()返回5623.22998046875
但是调用doubleResult.doubleValue()正确返回5623.23
但我不能完全肯定,如果它是一个正确的解决方案。
使用一个BigDecimal
代替float
/ double
。有很多数字不能被表示为二进制浮点数(例如,0.1
)。所以,你要么必须始终轮结果到已知精度或使用BigDecimal
。
我发现了以下解决方案:
public static Double getFloatAsDouble(Float fValue) {
return Double.valueOf(fValue.toString());
}
如果您使用的浮动和双击的而不是浮动和双击的使用以下命令:
public static double getFloatAsDouble(float value) {
return Double.valueOf(Float.valueOf(value).toString()).doubleValue();
}
花车,本质上是不准确的,总是有整齐的圆“的问题”。如果精度是非常重要的,那么你可以考虑重构你的应用程序中使用十进制或BigDecimal的。
是,浮体在计算上比在处理器的支持,因为的小数更快。但是,你想快速或准确的?
有关的信息这来自下项目48 - 避免浮点和双精度时是必需的,有效的Java第二版由Joshua布洛赫精确值。这本书是果酱挤满了好东西,绝对值得一看。
工作的呢?
float flt = 145.664454;
Double dbl = 0.0;
dbl += flt;