【问题标题】:Kotlin double greater than float wrong expression resolvingKotlin double 大于 float 错误表达式解决
【发布时间】:2020-03-09 13:31:34
【问题描述】:
我遇到了一个问题,我想知道预期的行为是否正确,或者我是否发现了错误。
鉴于此:
0.08 > 0.08 == false
0.08 > 0.08F == true
0.08 > 0.08F.toDouble() == true
0.08.toFloat() > 0.08F == false
为什么第三个表达式不为假?
有什么想法吗?
【问题讨论】:
标签:
kotlin
floating-point
double
expression
【解决方案1】:
这不是错误,它是基于舍入错误。
执行以下代码:
val d = 0.08
val f = 0.08F
val fd = f.toDouble()
print("%.20f".format(d) + "\n")
print("%.20f".format(f) + "\n")
print("%.20f".format(fd))
为您提供以下输出:
0.08000000000000000000
0.07999999821186066000
0.07999999821186066000
如您所见,0.08 双精度值(直到小数点后 20 位)精确到 0.08,而浮点数(由于精度较低)无法精确表示,因此它包含一个四舍五入的值,稍微有点低于0.08
将近似(略低)的 0.08 浮点数转换为双精度并不会提高精度,浮点数仍然存在舍入误差,导致转换后的双精度值略低。
// 编辑:如果您对浮点数的工作原理感兴趣,我建议您查看wikipedia article on floating point arithmetic 和这个问题:Is floating point math broken?
【解决方案2】:
这是对existing answer 的补充。 Java BigDecimal 有两个用于分析浮点行为的有用属性。从float 或double 到BigDecimal 的转换是精确的,它的默认字符串转换也是如此。这些属性的最简单用途是打印浮点表达式的确切值。 BigDecimal 算术也可用于,例如,在研究舍入时找到 double 与其邻居之间的中点。
这个程序:
import java.math.BigDecimal;
public strictfp class Test {
public static void main(String[] args) {
System.out.println(new BigDecimal(0.08));
System.out.println(new BigDecimal(0.08f));
}
}
输出:
0.08000000000000000166533453693773481063544750213623046875
0.07999999821186065673828125
这确认 0.08 表示为每种格式的预期精度,并且double 表示严格大于float。