Последовательность повторений в Java / Python / Mathematica - PullRequest
3 голосов
/ 09 октября 2009

Как вы можете написать следующее утверждение на данных языках?

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 ]

8 голосов
/ 09 октября 2009

Mathematica

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

(Обратите внимание на трюк для запоминания .)

Кроме того, [n] сходится (очень быстро) к sqrt (3) -1:

Solve[x == 1 - 1/(x+3), x]
4 голосов
/ 09 октября 2009

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)
3 голосов
/ 09 октября 2009

Mathematica:

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

Я заменил k = n + 1, потому что это упрощает выражение. Результат эквивалентен.

3 голосов
/ 09 октября 2009

Java

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
2 голосов
/ 09 октября 2009

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

Я стараюсь избегать написания "while True" или чего-то подобного, если могу этого избежать. Почти наверняка ни один код, который я напишу, не зациклится навсегда . В этом случае это бежало шестнадцать раз для меня. Шестнадцать намного меньше, чем ℵ-ноль.

1 голос
/ 19 апреля 2011

Однострочник в 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...