数値Xのフィボナッチ数を計算する

フォボナッチ数とは

フォボナッチ数列は各項が直前の二項の和になっているような数列
フィボナッチ数はその各項

漸化式は一般に

Fibonacci(n) = Fibonacci(n-1) + Fibonacci(n-2)

ただし n は 2 以上、0 と 1 のときは 0 と 1

Fibonacci(0) = 0
Fibonacci(1) = 1

一般項

Fibonacci(n) = (( 1 + √5 ) / 2 )n - ( 1 - √5 ) / 2 )n ) / √5

一般項

一般項の定義をそのままコードに

float	fibonacci( float	n ){
	float	sqrt_5 = sqrtf( 5.0f );
	return	( powf((( 1.0f + sqrt_5 ) * 0.5f ), n ) - powf((( 1.0f - sqrt_5 ) * 0.5f ), n )) / sqrt_5;
}
int	main(){
	for( int	n = 0; n < 13; ++n ){
		debug_printf( "%f\n", fibonacci( static_cast<float>(n)));
	}
	return	0;
}

再帰

一般項を使うと√が出てきたりして困るので、漸化式の通り再帰を使って整数だけで書くと

int	fibonacci( int	n ){
	int	result = n;
	if( n >= 2 ){
		result = fibonacci( n-2 ) + fibonacci( n-1 );
	}
	return	result;
}
int	main(){
	for( int	n = 0; n < 13; ++n ){
		debug_printf( "%d\n", fibonacci( n ));
	}
	return	0;
}

ループ:その1

再帰はループにできるので

int	fibonacci( int	N ){
	int	p3 = 0;
	if( N ){
		int	p1 = 0;
		int	p2 = 1;
		int	n = 1;
		do{
			p3 = p1 + p2;
			p1 = p2;
			p2 = p3;
		}while( ++n < N );
	}
	return	p3;
}
int	main(){
	for( int	n = 0; n < 13; ++n ){
		debug_printf( "%d\n", fibonacci( n ));
	}
	return	0;
}

ループ:その2

void	fibonacci( int	N ){
	debug_printf( "0" );
	if( N ){
		debug_printf( ",1" );
		int	p1 = 0;
		int	p2 = 1;
		for( int	n = 0; n < N-1; ++n ){
			int	p3 = p1 + p2;
			p1 = p2;
			p2 = p3;
			debug_printf( ",%d", p3 );
		}
	}
	debug_printf( "\n" );
}
int	main(){
	for( int	n = 0; n < 13; ++n ){
		fibonacci( n );
	}
	return	0;
}

テンプレート:その1

テンプレートを使うとコンパイル時に決定されるので定数として利用できる

template<int N> struct fibonacci_helper_t {
	static const int	value = fibonacci_helper_t<N-1>::value + fibonacci_helper_t<N-2>::value;
};
template<> struct fibonacci_helper_t<0> {
	static const int	value = 0;
};
template<> struct fibonacci_helper_t<1> {
	static const int	value = 1;
};
template<int N> int	fibonacci(){
	return	fibonacci_helper_t<N>::value;
}
int	main(){
	debug_printf( "%d\n", fibonacci<10>());
	debug_printf( "%d\n", fibonacci<11>());
	debug_printf( "%d\n", fibonacci<12>());
	return	0;
}

テンプレート:その2

再帰条件がコンパイル時に決定できる再帰はテンプレートにできる

template<int N> struct fibonacci_helper_t {
	static const int	value = fibonacci_helper_t<N-1>::value + fibonacci_helper_t<N-2>::value;
	static void	print(){
		debug_printf( ",%d", value );
	}
};
template<> struct fibonacci_helper_t<0> {
	static const int	value = 0;
	static void	print(){
		debug_printf( "0" );
	}
};
template<> struct fibonacci_helper_t<1> {
	static const int	value = 1;
	static void	print(){
		debug_printf( ",1" );
	}
};
template<int lhs,int rhs> struct less_than_or_equal_to_t {
	static const bool	value = ( lhs <= rhs );
};
template<int max_value,int n = 0,bool = less_than_or_equal_to_t<n,max_value>::value> struct fibonacci_print_helper_t {
	static void	each(){
		debug_printf( "\n" );
	}
};
template<int N,int n> struct fibonacci_print_helper_t<N,n,true> {
	static void	each(){
		fibonacci_helper_t<n>::print();
		fibonacci_print_helper_t<N,n+1>::each();
	}
};
template<int N> void	fibonacci(){
	fibonacci_print_helper_t<N>::each();
}
int	main(){
	fibonacci<10>();
	fibonacci<11>();
	fibonacci<12>();
	return	0;
}