将 float 转换为 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

但是,如果不是强制转换,而是将浮点数输出为字符串,并将字符串解析为双精度字符串,我会得到我想要的:

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

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

原文由 Steve Armstrong 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1k
2 个回答

这并不是说您 实际上 获得了额外的精度 - 而是浮点数没有准确地表示您最初瞄准的数字。双精度 表示 原始浮点数; toString 显示已经存在的“额外”数据。

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

 float f = 0.1F;
double d = f;

那么 f 的值可能正好是 0.100000234523。 d 将具有完全相同的值,但是当您将其转换为字符串时,它会“相信”它具有更高的精度,因此不会提前四舍五入,您会看到已经存在但对您隐藏的“额外数字”。

当您转换为字符串并返回时,您最终会得到一个双精度值,它比原始浮点数更接近字符串值 - 但只有 您真的相信字符串值是您真正想要的值时,这才是好的。

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

原文由 Jon Skeet 发布,翻译遵循 CC BY-SA 4.0 许可协议

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

 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

原文由 Brecht Yperman 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题