在不损失精度的情况下将浮点数转换为双精度

我有一个原始的浮动,我需要作为一个原始的替身。简单地将浮子铸造成双倍,就给了我奇怪的额外精度。例如:

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

但是,如果不进行强制转换,而是将 float 作为字符串输出,并将字符串作为 double 进行解析,那么就可以得到我想要的结果:

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

还有比去 String 那儿再回来更好的办法吗?

280568 次浏览

这并不是说你的 事实上得到了额外的精度-这是浮动没有准确地表示数字,你最初的目标。双 准确地表示原来的浮点数; toString显示已经存在的“额外”数据。

例如(这些数字不对,我只是编造)假设你有:

float f = 0.1F;
double d = f;

那么 f的值可能正好是0.100000234523。d具有完全相同的值,但是当你把它转换成字符串时,它会“相信”它是精确到更高的精度,所以不会很早就四舍五入,你会看到“额外的数字”已经存在,但是对你隐藏了。

当你转换成一个字符串并返回时,你得到的是一个双精度值,它比原来的 float 更接近字符串值——但这只是好的 if,你真的相信字符串值是你真正想要的。

您确定 float/double 是在这里而不是 BigDecimal使用的合适类型吗?如果您试图使用具有精确十进制值(例如货币)的数字,那么 BigDecimal是更合适的 IMO 类型。

Use a BigDecimal instead of float/double. There are a lot of numbers which can't be represented as binary floating point (for example, 0.1). So you either must always round the result to a known precision or use BigDecimal.

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

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

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

这是 Float.toString(float),的合同所规定的,其中一部分内容是:

要打印多少个数字 小数部分[ & hellip; ] ? 那里 必须至少有一位数字 表示小数部分,并且 除此之外,还有 但是只有那么多, more digits as are needed to uniquely 将参数值与 adjacent values of type float. That is, suppose that x is the exact mathematical value represented by the 小数 有限非零元的这种方法 那么 f 必须是浮点数 值最接近 x; 或者,如果两个浮点数 值等于 x,然后是 f 肯定是其中之一 意义的重要部分 F 一定是0。

有关信息,请参阅 Joshua Bloch 的有效 Java 第二版第48条-当需要精确值时避免浮点数和双精度数。这本书里塞满了好东西,绝对值得一看。

我发现转换为二进制表示更容易理解这个问题。

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)));

You can see the float is expanded to the double by adding 0s to the end, but that the double representation of 0.27 is 'more accurate', hence the problem.

   111110100010100011110101110001
11111111010001010001111010111000100000000000000000000000000000
11111111010001010001111010111000010100011110101110000101001000

我今天遇到了这个问题,因为这个项目非常庞大,所以无法使用 BigDecimal 的重构。然而,我发现解决方案使用

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

这样就行了。

Note that calling result.doubleValue() returns 5623.22998046875

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

但我不完全确定这是否是正确的解决方案。

这个有用吗?

float flt = 145.664454;


Double dbl = 0.0;
dbl += flt;

我找到了下面的解决办法:

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

如果您使用 漂浮double而不是 漂浮Double,请使用以下内容:

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

一个非常有效的简单解决方案是从 float 的字符串表示解析 double:

double val = Double.valueOf(String.valueOf(yourFloat));

虽然效率不是很高,但很管用!

有一种方法可以将 Float 值转换为 Double 而不增加额外的精度

Float aFloat= new Float(0.11);
String s = aFloat.toString();
Double aDouble = Double.parseDouble(s);

此方法在转换时不会向 Float 值添加额外的精度。这种方法的唯一问题是通过创建额外的 tamp String 对象来使用 JVM 的内存。

When calling an toString() (aDouble.toString()) on Double will never add an extra precisions. The precisions will be added while type conversion.