ความลึกการเรียกซ้ำสูงสุดใน Python คืออะไรและจะเพิ่มได้อย่างไร


421

ฉันมีฟังก์ชั่นวนซ้ำแบบหางนี่:

def recursive_function(n, sum):
    if n < 1:
        return sum
    else:
        return recursive_function(n-1, sum+n)

c = 998
print(recursive_function(c, 0))

มันทำงานขึ้นไปแล้วมันก็หยุดพักและถ่มน้ำลายออกn=997 RecursionError: maximum recursion depth exceeded in comparisonนี่เป็นเพียงการล้นสแต็กหรือไม่ มีวิธีที่จะหลีกเลี่ยงมันได้หรือไม่?



9
การบันทึกช่วยจำสามารถทำให้การทำงานของคุณเร็วขึ้นและเพิ่มความลึกแบบเรียกซ้ำที่มีประสิทธิภาพโดยการทำให้ค่าที่คำนวณได้ก่อนหน้านี้ยุติลงแทนที่จะเพิ่มขนาดสแต็ก
Cyoce

2
จำกัด การเรียกซ้ำโดยปกติคือ 1,000
Boris

1
@tonix ล่ามเพิ่มเฟรมสแต็ก ( line <n>, in <module>ในร่องรอยสแต็ค) และรหัสนี้ใช้เวลา 2 เฟรมสแต็กสำหรับn=1(เพราะกรณีฐานเป็นn < 1ดังนั้นn=1มันยังคงเกิดขึ้นอีก) และฉันเดาว่าการ จำกัด การเรียกซ้ำนั้นไม่รวมอยู่เนื่องจากเป็น "ข้อผิดพลาดเมื่อคุณกด 1,000" ไม่ใช่ "ข้อผิดพลาดหากคุณเกิน 1,000 (1001)" 997 + 2น้อยกว่า 1,000 จึงใช้งาน998 + 2ไม่ได้เพราะมันถึงขีด จำกัด แล้ว
Boris

1
@tonix no recursive_function(997)ทำงานได้998ดี เมื่อคุณเรียกrecursive_function(998)มันจะใช้ 999 stack stack และ 1 frame ถูกเพิ่มโดย interpreter (เพราะโค้ดของคุณจะทำงานเหมือนว่าเป็นส่วนหนึ่งของโมดูลระดับบนสุด) ซึ่งทำให้มันถึงขีด จำกัด 1,000
บอริส

คำตอบ:


469

มันเป็นตัวป้องกันการโอเวอร์โฟลว์ใช่ Python (หรือมากกว่านั้นการนำ CPython ไปใช้) ไม่ปรับการเรียกซ้ำแบบหางให้เหมาะสมและการเรียกซ้ำแบบไม่มีการควบคุมจะทำให้เกิดการล้นสแต็ก คุณสามารถตรวจสอบการ จำกัด การเรียกซ้ำด้วยsys.getrecursionlimitและเปลี่ยนการ จำกัด การเรียกซ้ำด้วยsys.setrecursionlimitแต่การทำเช่นนั้นเป็นสิ่งที่อันตราย - ขีด จำกัด มาตรฐานค่อนข้างอนุรักษ์นิยมเล็กน้อย แต่ Python stackframes อาจมีขนาดค่อนข้างใหญ่

Python ไม่ใช่ภาษาที่ใช้งานได้และการเรียกซ้ำแบบหางไม่ใช่เทคนิคที่มีประสิทธิภาพเป็นพิเศษ การเขียนอัลกอริทึมซ้ำถ้าเป็นไปได้มักเป็นความคิดที่ดีกว่า


4
จากประสบการณ์ของฉันคุณต้องเพิ่มขีด จำกัด ทั้งในsysและresourceโมดูล: stackoverflow.com/a/16248113/205521
Thomas Ahle

3
เป็นกลยุทธ์เพื่อแปลงเป็นรุ่นซ้ำมัณฑนากรหางเพิ่มประสิทธิภาพการโทรสามารถนำมาใช้
jfs

3
คุณสามารถใช้svn.python.org/projects/python/trunk/Tools/scripts/?hl=thเพื่อหาข้อ จำกัด ด้านบนของระบบปฏิบัติการของคุณ
Ullullu

8
สำหรับผู้ที่สนใจแหล่งที่มาขีด จำกัด การเรียกซ้ำเริ่มต้นจะถูกตั้งไว้ที่ 1,000 hg.python.org/cpython/file/tip/Python/ceval.c#l691และสามารถเปลี่ยนแปลงได้โดยใช้ API ที่hg.python.org/cpython /file/tip/Python/sysmodule.c#l643ซึ่งจะกำหนดขีด จำกัด เป็นค่าใหม่ที่hg.python.org/cpython/file/tip/Python/ceval.c#l7043
Pramod

16
การเรียกซ้ำหางเป็นเทคนิคที่มีประสิทธิภาพอย่างสมบูรณ์ในภาษาการเขียนโปรแกรมที่ปรับให้เหมาะกับมัน สำหรับการเรียงลำดับของปัญหาที่ถูกต้องมันอาจจะเป็นการแสดงออกถึงการใช้งานซ้ำ ๆ คำตอบอาจหมายถึง "ใน Python โดยเฉพาะ" แต่นั่นไม่ใช่สิ่งที่พูด
Peter R

135

ดูเหมือนว่าคุณต้องการตั้งค่าความลึกการเรียกซ้ำที่สูงขึ้น :

import sys
sys.setrecursionlimit(1500)

ในกรณีของฉันฉันลืมคำสั่ง return ในเคสพื้นฐานและมันเกิน 1,000 รายการ Python เริ่มโยนข้อยกเว้นนี้และฉันประหลาดใจเพราะฉันแน่ใจว่าไม่มี ของสแต็คที่จะสร้างเพื่อรัน
vijayraj34

sys.setrecursionlimit (50) หรือจำนวนเล็กน้อยมีประโยชน์หากโปรแกรมของคุณเข้าสู่การเรียกซ้ำและคุณต้องการให้ข้อความแสดงข้อผิดพลาดไม่ใช่หน้าและหน้าของข้อความเดียวกัน ฉันพบสิ่งนี้มีประโยชน์มากในขณะที่การดีบักโค้ดซ้ำของฉัน
peawormsworth

56

เพื่อหลีกเลี่ยงการล้นสแต็ค Python interpreter จำกัด ระดับความลึกของการเรียกซ้ำเพื่อช่วยให้คุณหลีกเลี่ยงการเรียกซ้ำที่ไม่สิ้นสุดทำให้เกิดสแต็คล้น ลองเพิ่มขีด จำกัด การเรียกซ้ำ ( sys.setrecursionlimit) หรือเขียนรหัสของคุณซ้ำโดยไม่เรียกซ้ำ

จากเอกสาร Python :

sys.getrecursionlimit()

ส่งคืนค่าปัจจุบันของขีด จำกัด การเรียกซ้ำความลึกสูงสุดของ Python interpreter stack ขีด จำกัด นี้ป้องกันการเรียกซ้ำแบบไม่สิ้นสุดทำให้เกิดการโอเวอร์โฟลว์ของ C stack และ Python ที่ล้มเหลว setrecursionlimit()มันสามารถตั้งค่าได้โดย


ใน Anaconda x64 ของฉัน 3.5 Python บน Windows ขีด จำกัด เริ่มต้นคือ 1,000
Guillaume Chevalier

30

หากคุณจำเป็นต้องเปลี่ยนขีด จำกัด การเรียกซ้ำ (เช่นในขณะที่ไขปริศนาการเขียนโปรแกรม) คุณสามารถกำหนดตัวจัดการบริบทอย่างง่ายเช่นนี้:

import sys

class recursionlimit:
    def __init__(self, limit):
        self.limit = limit
        self.old_limit = sys.getrecursionlimit()

    def __enter__(self):
        sys.setrecursionlimit(self.limit)

    def __exit__(self, type, value, tb):
        sys.setrecursionlimit(self.old_limit)

จากนั้นเมื่อต้องการเรียกฟังก์ชันที่มีขีด จำกัด ที่กำหนดเองคุณสามารถทำได้:

with recursionlimit(1500):
    print(fib(1000, 0))

เมื่อออกจากเนื้อความของwithคำสั่งขีด จำกัด การสอบถามซ้ำจะถูกกู้คืนเป็นค่าเริ่มต้น


คุณยังต้องการกระบวนการขีด จำกัด resourceกับการเรียกซ้ำ หากไม่มีคุณจะได้รับ Segmentation Fault และกระบวนการ Python ทั้งหมดจะล้มเหลวหากคุณsetrecursionlimitสูงเกินไปและพยายามใช้ขีด จำกัด ใหม่ (ประมาณ 8 เมกะไบต์ของเฟรมสแต็กซึ่งแปลเป็น ~ 30,000 สแต็กเฟรมด้วยฟังก์ชันง่าย ๆ ข้างบน แล็ปท็อปของฉัน).
บอริส

16

ใช้ภาษาที่รับประกันการเพิ่มประสิทธิภาพการโทรหาง หรือใช้การวนซ้ำ หรือมิฉะนั้นจะได้รับน่ารักกับตกแต่ง


36
ค่อนข้างจะขว้างลูกออกไปพร้อมกับอาบน้ำ
Russell Borogove

3
@Russell: มีเพียงหนึ่งในตัวเลือกที่ฉันเสนอให้คำแนะนำนี้
Marcelo Cantos

"รับความน่ารักด้วยการตกแต่ง" ไม่ใช่ตัวเลือก
นาย B

@ Mr.B เว้นแต่คุณต้องการulimit -sเฟรมมากกว่าสแต็คใช่แล้วคือstackoverflow.com/a/50120316
Boris

14

resource.setrlimit จะต้องใช้เพื่อเพิ่มขนาดสแต็กและป้องกัน segfault

ลินุกซ์เคอร์เนลจำกัด สแต็คของกระบวนการ

Python จัดเก็บตัวแปรโลคัลไว้ที่สแต็คของล่ามดังนั้นการเรียกซ้ำจึงใช้พื้นที่สแต็กของล่าม

หาก Python interpreter พยายามใช้เกินขีด จำกัด สแต็กเคอร์เนล Linux จะทำให้การแบ่งกลุ่มเกิดความผิดพลาด

ขนาด จำกัด ของสแต็กถูกควบคุมด้วยgetrlimitและการsetrlimitเรียกของระบบ

Python ให้การเข้าถึงการเรียกระบบเหล่านั้นผ่านresourceโมดูล

import resource
import sys

print resource.getrlimit(resource.RLIMIT_STACK)
print sys.getrecursionlimit()
print

# Will segfault without this line.
resource.setrlimit(resource.RLIMIT_STACK, [0x10000000, resource.RLIM_INFINITY])
sys.setrecursionlimit(0x100000)

def f(i):
    print i
    sys.stdout.flush()
    f(i + 1)
f(0)

แน่นอนถ้าคุณยังคงเพิ่ม ulimit RAM ของคุณก็จะหมดซึ่งจะทำให้คอมพิวเตอร์ของคุณหยุดชะงักเนื่องจากการเปลี่ยนความบ้าหรือฆ่า Python ผ่าน OOM Killer

จาก bash คุณสามารถดูและตั้งค่าขีด จำกัด สแต็ก (เป็น kb) ด้วย:

ulimit -s
ulimit -s 10000

ค่าเริ่มต้นสำหรับฉันคือ 8Mb

ดูสิ่งนี้ด้วย:

ทดสอบกับ Ubuntu 16.10, Python 2.7.12


1
การพยายามตั้งค่าrlimit_stackหลังจากการแก้ไขStack Clashอาจส่งผลให้เกิดความล้มเหลวหรือปัญหาที่เกี่ยวข้อง ดูที่ Red Hat Issue 1463241
jww

ฉันใช้ส่วนนี้ (ส่วนทรัพยากร Python) เพื่อช่วยให้การดำเนินการตามอัลกอริทึมของ Kosaraju กับชุดข้อมูลเฉลี่ย (ใหญ่) ของศาสตราจารย์ Tim Roughgarden การใช้งานของฉันทำงานในชุดเล็กแน่นอนว่าปัญหาที่เกิดขึ้นกับชุดข้อมูลขนาดใหญ่คือขีด จำกัด การเรียกซ้ำ / สแต็ก ... หรือใช่หรือไม่ ก็ใช่! ขอบคุณ!
nilo

9

ฉันรู้ว่านี่เป็นคำถามเก่า แต่สำหรับการอ่านเหล่านั้นฉันขอแนะนำให้ใช้การเรียกซ้ำสำหรับปัญหาเช่นนี้ - รายการเร็วกว่ามากและหลีกเลี่ยงการเรียกซ้ำทั้งหมด ฉันจะใช้สิ่งนี้เป็น:

def fibonacci(n):
    f = [0,1,1]
    for i in xrange(3,n):
        f.append(f[i-1] + f[i-2])
    return 'The %.0fth fibonacci number is: %.0f' % (n,f[-1])

(ใช้ n + 1 ใน xrange ถ้าคุณเริ่มนับลำดับฟีโบนักชีจาก 0 แทน 1)


13
ทำไมต้องใช้พื้นที่ O (n) เมื่อคุณสามารถใช้ O (1)
Janus Troelsen

11
ในกรณีที่ความคิดเห็นเกี่ยวกับพื้นที่ O (n) สับสน: อย่าใช้รายการ รายการจะเก็บค่าทั้งหมดเมื่อทั้งหมดที่คุณต้องการคือค่าที่ n อัลกอริทึมง่าย ๆ คือการเก็บหมายเลขฟีโบนักชีสองอันสุดท้ายและเพิ่มเข้าไปจนกว่าคุณจะได้หมายเลขที่คุณต้องการ มีอัลกอริทึมที่ดีกว่าเช่นกัน
Milimetric

3
@Mathime: xrangeถูกเรียกง่ายๆrangeใน Python 3
Eric O Lebigot

1
@EOL ฉันรู้เรื่องนี้
Mathime

7
@Mathime ฉันทำสิ่งที่ชัดเจนสำหรับผู้ที่อ่านความคิดเห็นเหล่านี้
Eric O Lebigot

9

แน่นอนว่าตัวเลข Fibonacci สามารถคำนวณได้ใน O (n) โดยใช้สูตร Binet:

from math import floor, sqrt

def fib(n):                                                     
    return int(floor(((1+sqrt(5))**n-(1-sqrt(5))**n)/(2**n*sqrt(5))+0.5))

ในฐานะที่เป็นผู้แสดงความคิดเห็นทราบมันไม่ได้เป็น O (1) แต่ O (n) 2**nเพราะ ความแตกต่างก็คือคุณจะได้รับเพียงค่าเดียวในขณะที่การเรียกซ้ำคุณจะได้รับค่าทั้งหมดFibonacci(n)จนถึงค่านั้น


8
ไม่มีขนาดความยาวสูงสุดในไพ ธ อน
pppery

8
เป็นที่น่าสังเกตว่าสิ่งนี้ล้มเหลวในการที่ใหญ่กว่าnเนื่องจากความไม่แน่นอนของจุดลอย - ความแตกต่างระหว่าง(1+sqrt(5))**nและ(1+sqrt(5))**(n+1)น้อยกว่า 1 ulp ดังนั้นคุณจึงเริ่มได้รับผลลัพธ์ที่ไม่ถูกต้อง

2
จริงๆแล้วไม่มีจำนวนเต็มขนาดใหญ่ใน NumPy …
Eric O Lebigot

@ Mego คืออะไร มันคือความแตกต่างระหว่าง(1+sqrt(5))**nและ((1+sqrt(5))**n)+1นั่นจะน้อยกว่า 1 ulp! (พิมพ์ผิดขนาดเล็ก) นอกจากนี้ {@} rwst นั่นไม่ใช่ O (1)! การคำนวณ2**nใช้เวลาอย่างน้อย O (n)
user202729

3
@ user202729 ที่ไม่จริงการคำนวณ2**nได้อย่างมีประสิทธิภาพ O (เข้าสู่ระบบ (n)) โดยใช้Exponentiattion โดย squaring
Sam

6

ฉันมีปัญหาที่คล้ายกันกับข้อผิดพลาด "เกินความลึกเรียกซ้ำสูงสุด" os.walkผมค้นพบข้อผิดพลาดที่ถูกเรียกโดยไฟล์เสียหายในไดเรกทอรีที่ผมวนรอบไปด้วย หากคุณมีปัญหาในการแก้ไขปัญหานี้และคุณกำลังทำงานกับเส้นทางของไฟล์โปรด จำกัด ให้แคบลงเนื่องจากอาจเป็นไฟล์ที่เสียหาย


2
OP ให้รหัสของเขาและการทดลองของเขาสามารถทำซ้ำได้ตามต้องการ มันไม่เกี่ยวข้องกับไฟล์ที่เสียหาย
T. Verron

5
คุณพูดถูก แต่คำตอบของฉันไม่ได้มุ่งเน้นไปที่ OP เพราะเมื่อสี่ปีที่แล้ว คำตอบของฉันมีวัตถุประสงค์เพื่อช่วยให้ผู้ที่มีข้อผิดพลาด MRD เกิดจากทางอ้อมโดยไฟล์เสียหาย - เนื่องจากนี่เป็นหนึ่งในผลการค้นหาครั้งแรก มันช่วยใครซักคนเพราะมันถูกโหวตแล้ว ขอบคุณสำหรับการลงคะแนนเสียง
Tyler

2
นี่เป็นสิ่งเดียวที่ฉันพบได้ทุกที่เมื่อค้นหาปัญหาของฉันที่เชื่อมต่อ "การสืบค้นกลับย้อนกลับ" กับไฟล์ที่เสียหาย ขอบคุณ!
Jeff

5

หากคุณต้องการได้รับหมายเลข Fibonacci เพียงไม่กี่คุณสามารถใช้วิธีเมทริกซ์

from numpy import matrix

def fib(n):
    return (matrix('0 1; 1 1', dtype='object') ** n).item(1)

มันเร็วอย่างที่ผู้ใช้ใช้อัลกอริทึมการยกกำลังสูง คุณได้รับคำตอบใน O (log n) และมันดีกว่าสูตรของ Binet เพราะมันใช้เลขจำนวนเต็มเท่านั้น แต่ถ้าคุณต้องการตัวเลขทั้งหมดของฟีโบนัชชีถึง n คุณควรที่จะทำเช่นนั้นโดยการท่องจำ


น่าเศร้าที่คุณไม่สามารถใช้ numpy ในการตัดสินการเขียนโปรแกรมแข่งขันมากที่สุด แต่ใช่ครับทางออกของคุณคือสิ่งที่ฉันโปรดปราน ฉันใช้การแก้เมทริกซ์กับปัญหาบางอย่าง มันเป็นทางออกที่ดีที่สุดเมื่อคุณต้องการจำนวนฟีโบนักชีจำนวนมากและคุณไม่สามารถใช้โมดูลัส หากคุณได้รับอนุญาตให้ใช้โมดูลัสช่วงเวลาที่ปิซาโน่เป็นวิธีที่ดีกว่าที่จะทำ
mentatkgs

4

ใช้เครื่องกำเนิดไฟฟ้าไหม?

def fib():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

fibs = fib() #seems to be the only way to get the following line to work is to
             #assign the infinite generator to a variable

f = [fibs.next() for x in xrange(1001)]

for num in f:
        print num

ฟังก์ชั่นดังกล่าวข้างต้น fib () ดัดแปลงมาจาก: http://intermediatepythonista.com/python-generators


1
เหตุผลในการกำหนดตัวสร้างให้กับตัวแปรนั้นเป็นเพราะ[fibs().next() for ...]จะสร้างตัวสร้างใหม่ทุกครั้ง
tox123

3

ตามที่ @alex แนะนำคุณสามารถใช้ฟังก์ชันตัวสร้างเพื่อทำสิ่งนี้ตามลำดับแทนการเรียกซ้ำ

นี่คือรหัสเทียบเท่าในคำถามของคุณ:

def fib(n):
    def fibseq(n):
        """ Iteratively return the first n Fibonacci numbers, starting from 0. """
        a, b = 0, 1
        for _ in xrange(n):
            yield a
            a, b = b, a + b

    return sum(v for v in fibseq(n))

print format(fib(100000), ',d')  # -> no recursion depth error

2

หลายคนแนะนำว่าการเพิ่มขีด จำกัด การเรียกซ้ำเป็นวิธีแก้ปัญหาที่ดี แต่ไม่ใช่เพราะจะมีการ จำกัด อยู่เสมอ ใช้วิธีแก้ปัญหาซ้ำ ๆ แทน

def fib(n):
    a,b = 1,1
    for i in range(n-1):
        a,b = b,a+b
    return a
print fib(5)

1

ฉันต้องการให้คุณตัวอย่างสำหรับการใช้บันทึกช่วยจำในการคำนวณ Fibonacci เช่นนี้จะช่วยให้คุณสามารถคำนวณตัวเลขที่มีขนาดใหญ่ขึ้นอย่างมีนัยสำคัญโดยใช้การสอบถามซ้ำ:

cache = {}
def fib_dp(n):
    if n in cache:
        return cache[n]
    if n == 0: return 0
    elif n == 1: return 1
    else:
        value = fib_dp(n-1) + fib_dp(n-2)
    cache[n] = value
    return value

print(fib_dp(998))

สิ่งนี้ยังคงเรียกซ้ำ แต่ใช้ hashtable อย่างง่ายที่อนุญาตให้นำหมายเลข Fibonacci ที่คำนวณก่อนหน้านี้มาใช้ใหม่แทนที่จะทำใหม่อีกครั้ง


1
import sys
sys.setrecursionlimit(1500)

def fib(n, sum):
    if n < 1:
        return sum
    else:
        return fib(n-1, sum+n)

c = 998
print(fib(c, 0))

1
คำตอบเดียวกันนี้ได้รับหลายครั้ง โปรดลบออก
ZF007

0

เราสามารถทำได้โดยใช้@lru_cacheมัณฑนากรและsetrecursionlimit()วิธีการ:

import sys
from functools import lru_cache

sys.setrecursionlimit(15000)


@lru_cache(128)
def fib(n: int) -> int:
    if n == 0:
        return 0
    if n == 1:
        return 1

    return fib(n - 2) + fib(n - 1)


print(fib(14000))

เอาท์พุต

3002468761178461090995494179715025648692747937490792943468375429502230242942284835863402333575216217865811638730389352239181342307756720414619391217798542575996541081060501905302157019002614964717310808809478675602711440361241500732699145834377856326394037071666274321657305320804055307021019793251762830816701587386994888032362232198219843549865275880699612359275125243457132496772854886508703396643365042454333009802006384286859581649296390803003232654898464561589234445139863242606285711591746222880807391057211912655818499798720987302540712067959840802106849776547522247429904618357394771725653253559346195282601285019169360207355179223814857106405285007997547692546378757062999581657867188420995770650565521377874333085963123444258953052751461206977615079511435862879678439081175536265576977106865074099512897235100538241196445815568291377846656352979228098911566675956525644182645608178603837172227838896725425605719942300037650526231486881066037397866942013838296769284745527778439272995067231492069369130289154753132313883294398593507873555667211005422003204156154859031529462152953119957597195735953686798871131148255050140450845034240095305094449911578598539658855704158240221809528010179414493499583473568873253067921639513996596738275817909624857593693291980841303291145613566466575233283651420134915764961372875933822262953420444548349180436583183291944875599477240814774580187144637965487250578134990402443365677985388481961492444981994523034245619781853365476552719460960795929666883665704293897310201276011658074359194189359660792496027472226428571547971602259808697441435358578480589837766911684200275636889192254762678512597000452676191374475932796663842865744658264924913771676415404179920096074751516422872997665425047457428327276230059296132722787915300105002019006293320082955378715908263653377755031155794063450515731009402407584683132870206376994025920790298591144213659942668622062191441346200098342943955169522532574271644954360217472458521489671859465232568419404182043966092211744372699797375966048010775453444600153524772238401414789562651410289808994960533132759532092895779406940925252906166612153699850759933762897947175972147868784008320247586210378556711332739463277940255289047962323306946068381887446046387745247925675240182981190836264964640612069909458682443392729946084099312047752966806439331403663934969942958022237945205992581178803606156982034385347182766573351768749665172549908638337611953199808161937885366709285043276595726484068138091188914698151703122773726725261370542355162118164302728812259192476428938730724109825922331973256105091200551566581350508061922762910078528219869913214146575557249199263634241165352226570749618907050553115468306669184485910269806225894530809823102279231750061652042560772530576713148647858705369649642907780603247428680176236527220826640665659902650188140474762163503557640566711903907798932853656216227739411210513756695569391593763704981001125

แหล่ง

Functionools lru_cache


0

เราสามารถใช้รูปแบบการเขียนโปรแกรมแบบไดนามิกจากล่างขึ้นบน

def fib_bottom_up(n):

    bottom_up = [None] * (n+1)
    bottom_up[0] = 1
    bottom_up[1] = 1

    for i in range(2, n+1):
        bottom_up[i] = bottom_up[i-1] + bottom_up[i-2]

    return bottom_up[n]

print(fib_bottom_up(20000))
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.