【问题标题】:What is wrong with this Python code about the Catalan numbers?这个关于加泰罗尼亚数字的 Python 代码有什么问题?
【发布时间】:2015-05-24 05:23:09
【问题描述】:

我是 Python 新手。这是一个家庭作业问题,但它很难,因为我只有一点 Java 经验。该代码应该使用其递归定义打印第一个加泰罗尼亚数字:

C(n + 1) = C(n) * (4n + 2) / (n + 2)

编辑:

我当前的代码看起来像这样,剩下的唯一问题是使用 savetxt() 方法将我通过此代码获得的所有 C(n) 数字放入一个 txt 中。

import numpy

c = []
c.append(1)
for i in xrange(0,1000000000):
    c.append((4*i+2)*c[i]/(i+2))
    print (c[i])
    if c[i]>= 1000000000:
        break


numpy.savetxt("catalan",numpy.c_[i, c[i]])

在最后一个问题解决后,我会尝试答案中建议的其他版本(比如先填充一个零数组)。

【问题讨论】:

  • 这里不需要 if 语句来中断循环
  • 您只是使用numpy 来导出数据,这似乎效率不高!如果您事先创建了一个空数组(例如使用numpy.zeros),您可以索引所有这些数组。
  • 对不起,我忘了添加问题:查找并列出所有小于 1.000.000.000 的 C(n) 的 n 和 C(n)。 for 循环中的范围表明最后一个 C(n) 数不会是十亿分之一 C(n)。我可以细化 for 循环的范围(或使用 while,但我们还没有在课程中使用它,所以我必须弄清楚)。
  • 我会尝试使用空数组,jonrsharpe,谢谢!

标签: python numpy catalan


【解决方案1】:

索引超出范围。您的第一个 i 等于 1,但 c 只有一个元素,即索引 0。所以只需将范围更改为 (0,1000000000)。

顺便说一句,不要使用range,使用xrange,它会更快并且占用更少的内存。当您使用range 时,Python 会创建一个该大小的数组。大小为 1000000000 的数组需要大量内存。相反,xrange 创建了一个迭代器,因此它占用的内存要少得多。

【讨论】:

  • 它似乎可以工作(范围内存错误,但 xrange 没有错误)。我现在正在搜索文件输出,我将编辑此评论并接受您的答案(不幸的是,我不允许将您的答案标记为有用,但这是一个非常有用的简短答案,对此我非常感谢很多!)。编辑:不幸的是,该文件只有这一行:“1.900000000000000000e+01 1.767263190000000000e+09”。
  • 是的,还请注意,在 for 循环之外,i 采用最后一个值,因此您只需将最后一个附加到 numpy
  • 那是我的下一个问题:在 savetxt() 方法中编写 for-stlye 循环是如何实现的?我记得类似 [0: x]。
  • 是的,虽然这会给你从 0 到 x-1 的所有 c 值,因为它不包括最后一个值
【解决方案2】:
for i in range(0, 1000000000):

这应该可行。

在您的第一次迭代中,您尝试使用 c[1],但它不存在。 您只有 c[0] 的值,因此列表索引超出范围。

【讨论】:

  • 感谢您的清理!不过,代码还有更多问题(请参阅我的其他 cmets 的其他答案)。
【解决方案3】:

您可以通过实际使用数组更好地利用numpy(这也使代码看起来更像我认为您最初拥有的那样):

import numpy as np

def catalan(x):
    """Create an array of the first x 'Catalan numbers'."""
    c = np.zeros(x)
    c[0] = 1
    for n in xrange(x-1):
        c[n+1] = c[n] * ((4 * n) + 2) / (n + 2)
    return c

如果你能想出一个非递归的定义,你可以显着加快速度(参见例如Is a "for" loop necessary if elements of the a numpy vector are dependant upon the previous element?)。请注意,这些数字会很快变大(您只能将前 34 个放入 64 位整数中)!

【讨论】:

  • 我认为你可以完全摆脱循环,例如a = np.arange(15)(((4*a)+2)/(a+2)).cumprod()(您可能希望将其转换为整数数组)。但是,正如您所说,数字很快就会变大,并且可能会溢出!
  • 感谢您的回答,我看起来确实更熟悉。如果我没记错的话,我只需要以 np.savetxt("...",np.c_[i,catalan[i]]) 结束。对吗?
  • @ajcr 这不是相当同一系列(1, 2, 4, 8, 24 vs 1, 1, 2, 5, 14
  • @MitlasóczkiBence 你为什么不试试看?
  • 你确定它会制作其他系列吗? (((4*a)+2)/(a+2)).cumprod() 生成了一个包含 1, 2, 5, 14, 42, 132, 429, ... 的数组 - 我运行它时 n = 1, 2, 3, 4, ... 的加泰罗尼亚数字。
【解决方案4】:

这几乎与Python:: "IndexError: list index out of range" 完全相同;在那里我建议不要使用递归,而应该只使用迭代公式来产生加泰罗尼亚数字;在您的情况下,您使用的是迭代方法,但是将它们存储到一个数组中。与创建一个数组来存储所有 n 加泰罗尼亚数字相比,我的方法非常节省内存:

def catalans():
    C = 1
    n = 0
    while True:
        yield C
        C = 2 * (2 * n + 1) * C // (n + 2)
        n += 1

with open('catalan', 'w') as output:
    for n, C in enumerate(1, catalans()):
        print(n, C, file=output)
        if C >= 1000000000:
            break

【讨论】:

  • 这个问题很可能在大学编程课程中很常见。但是,编写(复制)我不懂的代码是没有用的:我的目标是完成作业,并熟悉我在课程中看到的方法。在您编写的代码中,yield、itertools 和 list 对我来说是未知的,并且不应该用于解决问题。不过还是谢谢你的回答!
【解决方案5】:

如果你使用while会不会很容易?

C1,C2 = 1.0, 1.0
n=0
while C1<=1000000000:
    print(C1)
    C1,C2 = (((4*n+2)/(n+2)) * (C1)), C1
    n+=1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-26
    • 1970-01-01
    相关资源
    最近更新 更多