在Kotlin中,123.456
是有效的Double
值,但是123.456F.toDouble()
的结果是123.45600128173828
-大概只是两者之间处理精度的方式。
我希望能够在两者之间自由转换,特别是针对这样的情况:
123.456F -> 123.456 // Float to Double
123.456 -> 123.456F // Double to Float
在这种情况下如何将浮点数转换为双精度并保持精度?
答案 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的例程将通过适当舍入来消除这种差异。但这并不总是能得到您期望的结果。
当您需要范围广泛的值(例如,在科学和技术用途中)时,浮点数非常有用,但不必在乎它们的精确存储。