在递归循环中,为什​​么这个值会改变?

时间:2014-09-14 22:47:16

标签: recursion floating-point binary floating-point-precision approximation

我的教授有一个程序,它接受一个种子和函数,并递归输出并从那里输入一个值。

基本思想是你有一些f(x),你从一个x_0开始,所以f(x_0)= x_1。然后你有x_2 = f(x_1),依此类推,使得x_n = f(x_ {n-1})。

无论如何,你有时会得到这样的周期。例如,让f(x)= 2x mod 1。

在一个程序中,你可以输入0.2并期望一个周期:(0.2,0.4,0.3,0.6,0.2,...)

但最终他的程序做了一些奇怪的事情......在第50次迭代中,你得到一个0.20001,你会期望0.2,然后因此,程序突破循环并达到1,然后你得到所有输出之后是0。

我认为这与计算机的近似值有关,但我不知道为什么它最终会计算0.20001而不是0.2。有人可以给我一个技术解释吗?

1 个答案:

答案 0 :(得分:1)

浮点运算是确定性的(*)。

您认为您正在看到初始周期阶段然后更改为其他内容(“0.2,0.4,0.3,0.6,0.2”),但如果您以足够的精度打印这些值(使用格式{{1}如果你使用C语言或C语言),你会发现第一个“0.2”与第二个“0.2”不同。

如果在第一阶段真的重复了任何值,那么序列实际上是周期性的,所有其他值将无限重复,就像你期望的那样。


(*)除非您使用即时编译和糟糕的浮点语义编写语言。 Java可以及时编译,但浮点运算的含义是非常严格定义的,并且操作必须在即时编译之前和之后实现此定义,这样就不会留下奇怪的行为。 C#的浮点运算定义很奇怪,程序可能会因为即时编译而在一段时间后改变行为,但这可能是唯一一种具有如此可怕属性的广泛使用的语言。