我刚刚开始学习 C++,这是我用于生成斐波那契数列的 C++ 代码。
#include <iostream>
using namespace std;
int main()
{
int n;
while(true){
cout << "Enter the number of terms upto which a the fibonocci sequence should be generated: ";
cin >> n;
cout << "------------------------" << endl;
long long fib1 = 1;
long long fib2 = 1;
long long fibnext;
cout << 1 << " " << fib1 << endl << 2 << " " << fib2 <<endl;
for (int i =1; i <= n-2; ++i){
fibnext = fib1 + fib2;
fib1 = fib2;
fib2 = fibnext;
cout << i+2 << " " << fibnext << endl;
}
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
此代码在第 92 项之前生成正确的数字,但在第 93 项中出错。我不知道为什么。我的猜测是它与 fib1、fib2 和 fibnext 的数据类型有关。我怎样才能使我的代码正确,以便它生成任意数字的序列?
编辑:
我生成了前 100 个术语,结果如下:
Enter the number of terms upto which a the fibonocci sequence should be generated:
100
------------------------
1 1
2 1
3 2
4 3
5 5
6 8
7 13
8 21
9 34
10 55
11 89
12 144
13 233
14 377
15 610
16 987
17 1597
18 2584
19 4181
20 6765
21 10946
22 17711
23 28657
24 46368
25 75025
26 121393
27 196418
28 317811
29 514229
30 832040
31 1346269
32 2178309
33 3524578
34 5702887
35 9227465
36 14930352
37 24157817
38 39088169
39 63245986
40 102334155
41 165580141
42 267914296
43 433494437
44 701408733
45 1134903170
46 1836311903
47 2971215073
48 4807526976
49 7778742049
50 12586269025
51 20365011074
52 32951280099
53 53316291173
54 86267571272
55 139583862445
56 225851433717
57 365435296162
58 591286729879
59 956722026041
60 1548008755920
61 2504730781961
62 4052739537881
63 6557470319842
64 10610209857723
65 17167680177565
66 27777890035288
67 44945570212853
68 72723460248141
69 117669030460994
70 190392490709135
71 308061521170129
72 498454011879264
73 806515533049393
74 1304969544928657
75 2111485077978050
76 3416454622906707
77 5527939700884757
78 8944394323791464
79 14472334024676221
80 23416728348467685
81 37889062373143906
82 61305790721611591
83 99194853094755497
84 160500643816367088
85 259695496911122585
86 420196140727489673
87 679891637638612258
88 1100087778366101931
89 1779979416004714189
90 2880067194370816120
91 4660046610375530309
92 7540113804746346429
93 -6246583658587674878
94 1293530146158671551
95 -4953053512429003327
96 -3659523366270331776
97 -8612576878699335103
98 6174643828739884737
99 -2437933049959450366
100 3736710778780434371
Run Code Online (Sandbox Code Playgroud)
看看下面的值表:
4660046610375530309 - 第 92 个斐波那契数
9223372036854775807 - 最大的 64 位二进制补码,2^63 - 1
12200160415121876738 - 第 93 个斐波那契数
18446744073709551615 - 最大的 64 位无符号,2^64 - 1
正如你所看到的,一个64位二进制补码型(这是几乎可以肯定的是什么long long类型是你的情况)有足够的容量来存储92次Fibonacci数,但93次一个是因为它太大。
所以你看到的是溢出,数字环绕到负空间(实际发生的是未定义的行为,不能保证你会看到任何特定的结果,只是溢出到负数是一种常见的情况) .
如果您想计算超过92 nd 的斐波那契数,您将需要一种“更广泛”的数据类型,一种能够处理更大数字的数据类型。切换到unsigned long long将允许计算93次(参见上表中的第四个条目中,64位无符号变型的限制),但除此之外,什么都没有。
它不会去否定任何更多(因为它是无符号),但它会仍然给出一个错误的结果,因为在94日似乎是比93小RD,一些在Fibonacci序列中显然是不可能的,其中的每个术语的总和前两个术语,始终为正:
:
92 7540113804746346429
93 12200160415121876738
94 1293530146158671551 <<<--- ???
95 13493690561280548289
Run Code Online (Sandbox Code Playgroud)
对于更大的值,您可以切换到任意精度(通俗地称为“bignum”)数学库,例如MPIR。
举例来说,这是您修改后的原始代码以使用 MPIR 并输出前一千个斐波那契数:
#include <mpir.h>
#include <iostream>
// Helper function for checked output.
void OutZ(int num, mpz_t &x) {
static char textX[10000]; // can handle up to fib(47846)
if (gmp_snprintf(textX, sizeof(textX), "%Zd", x) >= sizeof(textX)) {
std::cout << "*** ERROR: Number was too big, need more space\n";
exit(1);
}
std::cout << num << " " << textX << '\n';
}
int main() {
// Initialise all MPIR integers to specific values.
mpz_t fib1, fib2, fib3;
mpz_init_set_ui(fib1, 1); // fib1 = 1
mpz_init_set_ui(fib2, 1); // fib2 = 1
mpz_init(fib3); // fib3 = 0
// No need for helper, these first two are well-known.
std::cout << "1 1\n2 1\n";
// Now do the rest of them.
for (int i = 3; i <= 1000; ++i) {
mpz_add(fib3, fib1, fib2); // fib3 = fib1 + fib2
mpz_set(fib1, fib2); // fib1 = fib2
mpz_set(fib2, fib3); // fib2 = fib3
OutZ(i, fib3);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
最后几行是(大约 0.01 秒后,所以效率方面还不错):
999 26863810024485359386146727202142923967616609318986952340123175997617981700247881689338369654483356564191827856161443356312976673642210350324634850410377680367334151172899169723197082763985615764450078474174626
1000 43466557686937456435688527675040625802564660517371780402481729089536555417949051890403879840079255169295922593080322634775209689623239873322471161642996440906533187938298969649928516003704476137795166849228875
Run Code Online (Sandbox Code Playgroud)
你可以通过要求Wolfram Alpha 给你fib(1000)来验证最后一个:
Result:
43466557686937456435688527675040625802564660517371780402481729089536555417949051890403879840079255169295922593080322634775209689623239873322471161642996440906533187938298969649928516003704476137795166849228875
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1844 次 |
| 最近记录: |