【问题标题】:Recurrence sequence in Java / Python / MathematicaJava / Python / Mathematica中的递归序列
【发布时间】:2010-12-05 03:50:55
【问题描述】:

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

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

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

我在 Mathematica 中的尝试

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

问题显然出在这个a[(x+1)_] 上。 但是,我不知道如何在 Mathematica 中迭代。

【问题讨论】:

  • 到目前为止你有什么?
  • 我很笨。下划线是运算符吗?
  • @Drew:我认为它只是表示下标。
  • 确实如此。但在 Mathematica 中,它作为“任何表达式”模式具有特殊含义。 (foo_ 表示“任何模式,以下称为 foo”。)

标签: java python wolfram-mathematica sequence


【解决方案1】:

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】:

    数学:

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

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

    【讨论】:

      【解决方案3】:

      数学

      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]
      

      【讨论】:

        【解决方案4】:

        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”之类的。几乎可以肯定,我编写的任何代码都不会永远循环。在这种情况下,它为我运行了 16 次。 16 比 ℵ-null 少很多。

        【讨论】:

          【解决方案5】:

          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)
          

          【讨论】:

          • 你的答案有两个步骤:1.解决极限,然后2.选择非常小的epsilon。 - 如何通过 Python 计算限制?
          • * 你会使用 Lorenzo 的方法来获得限制吗?
          • 你会如何定义 main 函数? 像这样 'def f(x): 1.0 - (1.0 / (float(x) + 3.0))'
          • @Masi,def main(): print limit(f) 之类的东西就足够了,但是 f 已定义,并且对于我展示的 limit 的任何实现。
          【解决方案6】:

          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
          

          【讨论】:

            猜你喜欢
            • 2023-03-22
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-03-23
            • 1970-01-01
            • 1970-01-01
            • 2019-05-13
            • 1970-01-01
            相关资源
            最近更新 更多