Java / Python / Mathematica中的重复序列

时间:2009-10-08 21:12:04

标签: java python wolfram-mathematica sequence

如何用给定的语言编写以下语句?

a(0) = 1
a_(n+1) = 1 - 1 / ( a_n + 3)

我需要在n时找到a_n -> 0.732050...的最小值。

我在Mathematica的尝试

a[(x+1)_] = 1 - 1/(a[x_] + 3)

问题显然在于a[(x+1)_]。 但是,我不知道如何在Mathematica中迭代地完成它。

6 个答案:

答案 0 :(得分:8)

数学

a[0] = 1;
a[n_] := a[n] = 1 - 1/(a[n-1] + 3)

(注意memoization trick。)

此外,a [n]收敛(非常快)到sqrt(3)-1:

Solve[x == 1 - 1/(x+3), x]

答案 1 :(得分:4)

Python,最简单:

def a(n):
  if n == 0: return 1
  return 1 - 1 / float(a(n-1) + 3)

# limit is sqrt(3) - 1
limit = 3.0 ** 0.5 - 1.0

# get 9 digits' precision
i = 0
while abs(a(i) - limit) > 1.0e-9:
  i += 1

print i

这会发出8,表明可能无法保证诸如递归消除或记忆的优化。

当然,通常我们希望以数字方式而不是分析方式获得限制,因此循环的正常方式会有所不同 - 最好封装在更高阶函数中......:

# get a function's limit numerically
def limit(f, eps=1.0e-11):
  previous_value = f(0)
  next_value = f(1)
  i = 2
  while abs(next_value - previous_value) > eps:
    previous_value = next_value
    next_value = f(i)
    i += 1
  return next_value

非平凡循环逻辑通常最好封装在生成器中:

def next_prev(f):
  previous_value = f(0)
  i = 1
  while True:
    next_value = f(i)
    yield next_value, previous_value
    i += 1
    previous_value = next_value

在这个生成器的帮助下,limit HOF变得更加简单:

def limit(f, eps=1.0e-11):
  for next_value, previous_value in next_prev(f):
    if abs(next_value - previous_value) < eps:
      return next_value

请注意分离是多么有用:next_prev体现了“获取函数的下一个和上一个值”的概念,limit只处理“循环何时终止”。

最后但并非最不重要的是,itertools经常为生成器提供一个很好的替代方案,让你以快速的方式封装挑剔的迭代逻辑(虽然它确实需要一些习惯......; - ):

import itertools

def next_prev(f):
  values = itertools.imap(f, itertools.count())
  prv, nxt = itertools.tee(values)
  nxt.next()
  return itertools.izip(prv, nxt)

答案 2 :(得分:3)

爪哇

double A = 1;
int n = 0;
while (true) {
  System.out.println(n + " " + A);
  A = 1 - 1 / (A + 3);
  n++;
}

的Python

A = 1.0
n = 0
while 1:
  print n, A
  A = 1 - 1 / (A + 3)
  n += 1

答案 3 :(得分:3)

数学:

a[0] := 1
a[k_] := 1 - 1/(a[k - 1] + 3)

我替换了k = n + 1因为这使得表达式更简单。结果是等价的。

答案 4 :(得分:2)

<强>的Python

next = lambda x: 1.0 - (1.0 / (float(x) + 3.0))
last, z, count = -1, 0.0, 0
while last != z:
  print count, z
  last, z, count = z, next(z), count+1

我尽量避免写“真实”或者如果我可以避免它。几乎可以肯定,我编写的代码不会永远循环 。在这种情况下,它为我跑了十六次。十六岁比ℵ-null少得多。

答案 5 :(得分:1)

Mathematica中的单行代码,它列出了序列的确切元素:

In[66]:= NestWhileList[1 - 1/(#1 + 3) &, 1, 
 RealExponent[Subtract[##]] > -8 &, 2]

Out[66]= {1, 3/4, 11/15, 41/56, 153/209, 571/780, 2131/2911, \
7953/10864, 29681/40545}

最后两个元素之间的差异小于10 ^ -8。因此,它进行了8次迭代:

In[67]:= Length[%]

Out[67]= 9
相关问题