2017-09-19 20 views
5

以下代码是从https://kotlinlang.org/docs/reference/functions.html?q=&p=0我可以比较Kotlin中两个浮点数是否相等吗?

此代码计算余弦的固定点,它是一个数学常数。它只需从1.0开始重复调用Math.cos,直到结果不再变化,结果为0.7390851332151607。

在我看来,我们无法比较两个浮点数是否相等,所以我认为if (x == y)的结果总是假的吧?

private fun findFixPoint(): Double { 
    var x = 1.0 
    while (true) { 
     val y = Math.cos(x) 
     if (x == y) return y 
     x = y 
    } 
} 
+0

如果你愿意,你可以比较两个浮点数,为什么你不能?这不是一种常见的情况,因为它是针对大多数问题的一种脆弱解决方案。你通常想要做的是比较一个差异的ε值或使用精确的十进制算术。在这种情况下,它看起来像一个有效的解决方案,因为它必然收敛到一定的值。 – DPM

+0

在某些语言中,比如Fortran,浮点数不是一个精确的,所以如果(x == y)返回y应该是if(ABS(x-y)<0.0000000001)返回y – HelloCW

回答

3

为了进一步扩展我的评论和更加精确,文档为您提供了关键。

Math.cos(double)

计算结果必须是内准确结果的1 ulp。结果 必须是半单调的。

ulp是编码的浮点数与下一个可以在数据类型中编码的数字(在本例中为double)之间的差异。

如果结果必须在1 ulp以内,那意味着结果可以是最多两个浮点值之一。

因此,计算不会停止的唯一方法是如果其中一个数字的输入将给您另一个数字。但是由于函数是半单调的,这意味着不可能发生。否则,你将有两个较高的值作为输入,使得较低的值作为输出,而较低的值给出较高的值作为输出。半单调意味着它只能在一个方向上进行(非常简单,有些不准确)。

1

在我看来,我们无法比较两个浮点数是否相等,所以我认为if(x == y)的结果总是为false,对吗?

不,这是错误的。您CAN比较两个浮点数是否相等,但它是无意义的。因为按定义浮点不准确。即使两个不同的计算在Math中具有相同的结果,但由于舍入误差,在程序中不必等同。它仍然有可能是平等的。

+0

谢谢!我假设手动计算100次后,Math.cos(x)将为0.7390851332151607,上面的代码将计算500次,直到x == yy,并且上面的代码再次运行时,可能需要计算800次,直到x = = yy,对吗? – HelloCW

+0

@HelloCW不,即使在数学上是平等的,也不能保证它们是平等的。 – Joshua

+0

谢谢!如果是这样,你为什么认为示例代码是正确的?我认为它应该是如果(ABS(x-y)<0.0000000001)返回y,示例代码将无限循环 – HelloCW