【问题标题】: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?

    【讨论】:

    • 最后一个指向Is floating point math broken? 的链接不是一个好的参考。那里的答案通常不是教程,并且通常试图用一种或另一种基本原理来“解释”错误,而不是给出学生使用浮点算术需要的背景和数学公式。
    【解决方案2】:

    这是对existing answer 的补充。 Java BigDecimal 有两个用于分析浮点行为的有用属性。从floatdoubleBigDecimal 的转换是精确的,它的默认字符串转换也是如此。这些属性的最简单用途是打印浮点表达式的确切值。 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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多