Kotlin-在保持精度的同时将Float转换为Double

时间:2019-05-14 12:48:29

标签: kotlin floating-point

在Kotlin中,123.456是有效的Double值,但是123.456F.toDouble()的结果是123.45600128173828-大概只是两者之间处理精度的方式。

我希望能够在两者之间自由转换,特别是针对这样的情况:

123.456F -> 123.456 // Float to Double

123.456 -> 123.456F // Double to Float

在这种情况下如何将浮点数转换为双精度并保持精度?

2 个答案:

答案 0 :(得分:2)

这很丑陋,但是您可以将Float转换为String,然后再转换回Double

val myDouble: Double = 123.456f.toString().toDouble()
// 123.456d

您始终可以将其封装在扩展功能中

fun Float.toExactDouble(): Double = 
    this.toString().toDouble()

val myDouble = 123.456f.toExactDouble()

答案 1 :(得分:2)

  

在Kotlin中123.456是有效的Double值

实际上,那不是真的。 close 非常接近123.456,但不是精确 123.456。您所看到的就是这种后果。

所以您不能保持精度,因为您一开始就没有这种精度!

简短回答:

如果您需要精确的值,请不要使用浮点!

(尤其是:切勿将货币值存储在浮点中!参见例如this问题。)

最好的替代方法通常是BigDecimal,它可以以任意精度存储和计算小数。它们的效率较低,但是Kotlin的运算符重载使它们使用起来很轻松(不同于Java!)。

或者,如果您不打算进行任何计算,则可以将它们存储为String

或者,如果您只需要一定数量的小数位,则可以将它们全部扩展到Int s(或Long s)。

技术说明:

浮点数和双精度数使用二进制浮点;它们存储一个整数,以及2的整数次幂或除以。 (例如,3/4将被存储为3 *2⁻²。)这意味着它们可以精确存储各种二进制分数。

但是,就像您不能以小数形式存储1/3(即0.3333333333…一样,但是任何有限数目的数字都只是一个近似值),因此您不能以1/10的形式存储二进制数(这是0.000110011001100…)。这意味着二进制浮点数不能完全存储大多数十进制数

相反,它们存储与您想要的数字最接近的可能值。将它们转换为String的例程将通过适当舍入来消除这种差异。但这并不总是能得到您期望的结果。

当您需要范围广泛的值(例如,在科学和技术用途中)时,浮点数非常有用,但不必在乎它们的精确存储。