Thuật toán hiệu quả để tính toán số Fibonacci thứ


11

Số Fibonacci thứ có thể được tính trong thời gian tuyến tính bằng cách sử dụng lần lặp lại sau:n

def fib(n):
    i, j = 1, 1
    for k in {1...n-1}:
        i, j = j, i+j
    return i

Các th số Fibonacci cũng có thể được tính như [ φ n / n. Tuy nhiên, điều này có vấn đề với các vấn đề làm tròn chonthậm chí tương đối nhỏ. Có lẽ cónhiều cách để giải quyết vấn đề nàynhưng tôi không muốn làm điều đó.[φn/5]n

Có một thuật toán hiệu quả (logarit trong giá trị hoặc tốt hơn) để tính toán số Fibonacci thứ n không dựa vào số học dấu phẩy động? Giả sử rằng các phép toán số nguyên ( + , - , × , / ) có thể được thực hiện trong thời gian không đổi.nn+×/


5
Như một gợi ý, bài viết trên Wikipedia về các số Fibonacci có rất nhiều phương pháp.
Bút danh

xem stackoverflow.com/questions/14661633/ và liên kết trong đó và xung quanh.
Will Ness

Câu trả lời:


14

Bạn có thể sử dụng nguồn ma trận và danh tính Trong mô hình tính toán của bạn, đây là thuật toán O ( log n ) nếu bạn sử dụng bình phương lặp lại để thực hiện cấp nguồn.

[1110]n=[Fn+1FnFnFn1].
O(logn)

1
Đó là một cổ điển.
dfeuer

8
Bạn cũng có thể sử dụng danh tính này để rút ra các lần lặp lại F 2 n = F 2 n + 2 F n - 1 F n . F2n1=Fn2+Fn12F2n=Fn2+2Fn1Fn
tám

4

Bạn có thể đọc bài viết toán học này: Một thuật toán nhanh để tính toán các số Fibonacci lớn (Daisuke Takahashi): PDF .

Đơn giản hơn, tôi đã triển khai một số thuật toán của Fibonacci trong C ++ (không có và có GMP) và Python. Hoàn thành các nguồn trên Bitbucket. Từ trang chính, bạn cũng có thể theo liên kết đến:

  • Tài liệu trực tuyến C ++ HTML.
  • Một tài liệu toán học nhỏ: số Fibonacci - một số quan hệ để thực hiện các thuật toán tốt

Các công thức hữu ích nhất là:

  • F2n= =Fn+12-Fn-12= =2FnFn-1+Fn2
  • F2n+1= =Fn+12+Fn2

Hãy cẩn thận về thuật toán. Bạn không được tính cùng một giá trị nhiều lần. Một thuật toán đệ quy đơn giản (bằng Python):

def fibonacci_pair(n):
    """Return (F_{n-1}, F_n)"""
    if n != 0:
        f_k_1, f_k = fibonacci_pair(n//2)  # F_{k-1},F_k with k = n/2

        return ((f_k**2 + f_k_1**2,
                 ((f_k*f_k_1)*2) + f_k**2) if n & 1 == 0  # even
                else (((f_k*f_k_1)*2) + f_k**2,
                      (f_k + f_k_1)**2 + f_k**2))
    else:
        return (1, 0)

Ôi(đăng nhậpn)


2
Chào mừng bạn đến với Khoa học máy tính . Xin vui lòng bạn có thể thêm thông tin để trả lời của bạn? Hiện tại, không có gì nhiều hơn hai liên kết, vì vậy câu trả lời của bạn sẽ trở nên vô nghĩa nếu những liên kết đó bị chết hoặc các máy chủ mà chúng không có sẵn. Liên kết đến nhiều thông tin là tốt nhưng các liên kết ở đây là thông tin duy nhất. Ngoài ra, xin lưu ý rằng câu hỏi rất chắc chắn về các thuật toán, không phải về việc triển khai C ++. Việc triển khai có xu hướng che khuất các thuật toán đằng sau các chi tiết cụ thể về ngôn ngữ.
David Richerby

David, liên kết đầu tiên là một liên kết đến một bài báo toán học. Tiêu đề Một thuật toán nhanh [...] trả lời cho câu hỏi "Có thuật toán hiệu quả (logarit trong giá trị n hoặc tốt hơn) [...] không?" Liên kết thứ hai là một liên kết đến các triển khai khác nhau của tôi, trong C ++ Python và một tài liệu toán học nhỏ với một số công thức.
Olivier Pirson

2
Không, tiêu đề của bài viết, đó là những gì câu trả lời của bạn chứa, không có câu trả lời. Văn bản của bài viết, mà câu trả lời của bạn chứa hầu như không có, nghe có vẻ như nó có thể trả lời câu hỏi. Nhưng Stack Exchange là một trang web câu hỏi và câu trả lời, không phải là một trang trại liên kết. (Và, không, tôi không gợi ý rằng bạn sao chép-dán bài viết vào câu trả lời của bạn. Nhưng cần có một bản tóm tắt.)
David Richerby

Nếu bạn muốn một bản tóm tắt, viết nó!
Olivier Pirson

0

O(log2n)

Kiểm tra cuốn sách miễn phí Matters Computational và mã pari / gp.


5
Tốt hơn để tóm tắt các ý tưởng thay vì chỉ đăng liên kết.
tám
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.