1. 程式人生 > >c語言:寫一個函式,輸入n,求斐波拉契數列的第n項(5種方法,層層優化)

c語言:寫一個函式,輸入n,求斐波拉契數列的第n項(5種方法,層層優化)

寫一個函式,輸入n,求斐波拉契數列的第n項。

斐波拉契數列1,1,2,3,5,8...當n大於等於3時,後一項為前面兩項之和。

解:方法1:斐波拉契數列的函式定義角度程式設計

#include<stdio.h>

int fibonacci(int n)

{

int num1=1, num2=1, num3=0,i;

if (n <= 2)

{

printf("斐波拉契數列的第%d項為:%d\n",n,num1);

}

else

{

for (i = 2; i < n; i++)

{

num3 = num1 + num2;

num1 = num2;

num2 = num3;

}

printf("斐波拉契數列的第%d項為:%d\n", n, num3);

}

return 0;

}

int main()

{

int num=0;

printf("請輸入一個正整數:");

scanf("%d", &num);

fibonacci(num);

return 0;

}

結果:

請輸入一個正整數:3

斐波拉契數列的第3項為:2

請按任意鍵繼續. . .

方法2:遞迴呼叫,很明顯優化了程式碼量

#include<stdio.h>

int fibonacci(int n)

{

if (n <= 0)

{

return 0;

}

if (n == 1)

{

return 1;

}

return fibonacci(n-1)+ fibonacci(n - 2);

}

int main()

{

int num = 0,ret=0;

printf("請輸入一個正整數:");

scanf("%d", &num);

ret=fibonacci(num);

printf("斐波拉契數列的第%d項為:%d\n", num,ret);

return 0;

}

結果:

請輸入一個正整數:4

斐波拉契數列的第4項為:3

請按任意鍵繼續. . .

方法3提高遞迴的效率,把已經求得的中間項儲存起來,就不用再重複進行計算了;其本質相當於方法一的思想

#include<stdio.h>

int fibonacci(int n)

{

int num1 = 1, num2 = 1, num3 = 0, i=0;

if (n <= 2)

{

return num1;

}

    for (i = 2; i < n; i++)

{

num3 = num1 + num2;

num1 = num2;

num2 = num3;

}

return num3;

}

int main()

{

int num = 0,ret=0;

printf("請輸入一個正整數:");

scanf("%d", &num);

ret=fibonacci(num);

printf("斐波拉契數列的第%d項為:%d\n", num,ret);

return 0;

}

結果:

請輸入一個正整數:3

斐波拉契數列的第3項為:2

請按任意鍵繼續. . .

方法4:直接運用數學公式法:f(n)={[(1+5^0.5)/2]^n - [(1-5^0.5)/2]^n}/(5^0.5)

#include<stdio.h>

#include<math.h>

int fibonacci(int n)

{

return (pow((1+sqrt(5.0))/2,n)- pow((1 - sqrt(5.0)) / 2, n))/ sqrt(5.0);

}

int main()

{

int num = 0, ret = 0;

printf("請輸入一個正整數:");

scanf("%d", &num);

ret = fibonacci(num);

printf("斐波拉契數列的第%d項為:%d\n", num, ret);

return 0;

}

結果:

請輸入一個正整數:4

斐波拉契數列的第4項為:3

請按任意鍵繼續. . .

方法5生僻的數學公式法

 f(n)   f(n-1)  =    1     1

[              ]   [          ]^(n-1)

 f(n-1) f(n-2)       1     0

該公式可用數學歸納法進行證明,在矩陣乘法的變換證明過程中,要注意運用斐波拉契數列的性質:後一項為前面兩項之和;該數學公式,應用矩陣的乘法,時間效率雖然低,但不夠實用,原始碼太過繁瑣,提供如下程式碼僅供參考

#include <cassert>

struct Matrix2By2

{

Matrix2By2

(

long long m00 = 0,

long long m01 = 0,

long long m10 = 0,

long long m11 = 0

)

:m_00(m00), m_01(m01), m_10(m10), m_11(m11)

{

}

long long m_00;

long long m_01;

long long m_10;

long long m_11;

};

Matrix2By2 MatrixMultiply

(

const Matrix2By2& matrix1,

const Matrix2By2& matrix2

)

{

return Matrix2By2(

matrix1.m_00 * matrix2.m_00 + matrix1.m_01 * matrix2.m_10,

matrix1.m_00 * matrix2.m_01 + matrix1.m_01 * matrix2.m_11,

matrix1.m_10 * matrix2.m_00 + matrix1.m_11 * matrix2.m_10,

matrix1.m_10 * matrix2.m_01 + matrix1.m_11 * matrix2.m_11);

}

Matrix2By2 MatrixPower(unsigned int n)

{

assert(n > 0);

Matrix2By2 matrix;

if (n == 1)

{

matrix = Matrix2By2(1, 1, 1, 0);

}

else if (n % 2 == 0)

{

matrix = MatrixPower(n / 2);

matrix = MatrixMultiply(matrix, matrix);

}

else if (n % 2 == 1)

{

matrix = MatrixPower((n - 1) / 2);

matrix = MatrixMultiply(matrix, matrix);

matrix = MatrixMultiply(matrix, Matrix2By2(1, 1, 1, 0));

}

return matrix;

}

long long Fibonacci_Solution3(unsigned int n)

{

int result[2] = { 0, 1 };

if (n < 2)

return result[n];

Matrix2By2 PowerNMinus2 = MatrixPower(n - 1);

return PowerNMinus2.m_00;

}

// ====================測試程式碼====================

void Test(int n, int expected)

{

if (Fibonacci_Solution1(n) == expected)

printf("Test for %d in solution1 passed.\n", n);

else

printf("Test for %d in solution1 failed.\n", n);

if (Fibonacci_Solution2(n) == expected)

printf("Test for %d in solution2 passed.\n", n);

else

printf("Test for %d in solution2 failed.\n", n);

if (Fibonacci_Solution3(n) == expected)

printf("Test for %d in solution3 passed.\n", n);

else

printf("Test for %d in solution3 failed.\n", n);

}

int _tmain(int argc, _TCHAR* argv[])

{

Test(0, 0);

Test(1, 1);

Test(2, 1);

Test(3, 2);

Test(4, 3);

Test(5, 5);

Test(6, 8);

Test(7, 13);

Test(8, 21);

Test(9, 34);

Test(10, 55);

Test(40, 102334155);

return 0;

}