Hãy tìm số thứ tự của số Fibonacci đầu tiên có 1000 chữ số
Problem PE025-1000-digit-Fibonacci-number
The Fibonacci sequence is defined by the recurrence relation:
Fn = Fn−1 + Fn−2, where F1 = 1 and F2 = 1.
Hence the first 12 terms will be:
F1 = 1
F2 = 1
F3 = 2
F4 = 3
F5 = 5
F6 = 8
F7 = 13
F8 = 21
F9 = 34
F10 = 55
F11 = 89
F12 = 144
The 12th term, F12, is the first term to contain three digits.
What is the index of the first term in the Fibonacci sequence to contain 1000 digits?
Đề bài
Dãy số Fibonacci được tạo thành bởi công thức:
Fn = Fn−1 + Fn−2
Trong đó F1 = 1 và F2 = 1. Dưới đây là 12 số Fibonacci đầu tiên:
F1 = 1
F2 = 1
F3 = 2
F4 = 3
F5 = 5
F6 = 8
F7 = 13
F8 = 21
F9 = 34
F10 = 55
F11 = 89
F12 = 144
Ta thấy F12 là số Fibonacci đầu tiên có 3 chữ số.
Hãy tìm số thứ tự của số Fibonacci đầu tiên có 1000 chữ số
Phân tích đề bài:
Dãy số Fibonacci thì quen thuộc với các lập trình viên rồi. Nhưng số có 1000 chữ số thì nó thành “số lớn” rồi.
Với Python thì số lớn không thành vấn đề nhưng với các ngôn ngữ lập trình khác cũng “căng”
Sau nguyên 1 ngày suy nghĩ cách giải quyết bài toán này mà không làm được theo cách nào hiệu quả hơn (mặc dù trên công thức toán học là có), tôi đành phải quay về giải quyết bằng cách “trâu bò”.
“Trâu bò” cũng phải có tính toán một chút. Vấn đề đầu tiên đó là thế nào là số có 1000 chữ số ?
Với số có n = 3 chữ số –> cận dưới là 100 = 10^2 –> 10 ^ (n-1)
Với số có n = 4 chữ số –> cận dưới là 1000 = 10^3 –> 10 ^ (n-1) … Với số có n = 1000 chữ số –> cận dưới là 10 ^ (n-1) –> 10 ^ 999
Chúng ta sẽ đặt một vòng lặp để khi nào số fi3 bắt đầu lớn hơn 10 ^ 999 thì dừng lại.
LIMIT_NUMBER = 1000
def find_fibonacci_number():
fi_1 = 1
fi_2 = 1
fi_3 = fi_1 + fi_2
limit = 10 ** (LIMIT_NUMBER - 1)
index = 3
while fi_3 <= limit:
fi_2, fi_1 = fi_3, fi_2
fi_3 = fi_2 + fi_1
index += 1
return index
Kết quả của bài toán:
Nguyens-MBP:PE-025 vinh.nguyenquang$ python3 1000_digit_fibonacci_number.py
The first term in the fibonnaci sequence to have more than 1000 digits is term number: 4782
elapsed time: 0.000904083251953125s
Nếu có ai tò mò số 1.000 chữ số này là số nào thì đây là đáp án:
1070066266382758936764980584457396885083683896632151665013235203375314520604694040621889147582489792657804694888177591957484336466672569959512996030461262748092482186144069433051234774442750273781753087579391666192149259186759553966422837148943113074699503439547001985432609723067290192870526447243726117715821825548491120525013201478612965931381792235559657452039506137551467837543229119602129934048260706175397706847068202895486902666185435124521900369480641357447470911707619766945691070098024393439617474103736912503231365532164773697023167755051595173518460579954919410967778373229665796581646513903488154256310184224190259846088000110186255550245493937113651657039447629584714548523425950428582425306083544435428212611008992863795048006894330309773217834864543113205765659868456288616808718693835297350643986297640660000723562917905207051164077614812491885830945940566688339109350944456576357666151619317753792891661581327159616877487983821820492520348473874384736771934512787029218636250627816
Một số vấn đề rút ra từ bài toán.
Ở đoạn này:
limit = 10 ** (LIMIT_NUMBER - 1)
Nếu sử dụng math.pow(x,y) có sẵn của Python, ta sẽ thu được kết quả khá buồn:
Traceback (most recent call last):
limit = math.pow(10, LIMIT_NUMBER - 1)
OverflowError: math range error
Đoạn tiếp theo
while fi_3 <= limit:
Tại sao không sử dụng: while len(fi_3) <= 1000:
Câu trả lời đó là nếu dùng len(fi_3)
, mỗi lần đến đoạn này trình thông dịch phải 1 lần “hỏi” cái fi_3 có độ dài là bao nhiêu –> Tốn kha khá thời gian với cái này
Source-code: PE-025