フーリエ展開

アバター
トム
記事: 4
登録日時: 15年前

フーリエ展開

投稿記事 by トム » 14年前

今回は前回とは打って変わってフーリエ展開のアルゴリズムを作りました。
ちょこちょこっと終わるかなと思っていたら思いのほか四苦八苦。
どこで計算がおかしくなっているのかがわかりにくかったです。

今回のポイント(?)は積分関数に関数ポインタを渡すところですか。
関数ポインタを使うのが今回が初めてだったので苦戦しました。

クラスのメンバ関数は引数として渡せないというのが大きな壁。
やむなく積分関数は冗長でわかりにくい関数になってしまいました。
しかし汎用性は一応キープ。

周期関数func()の内容だけ変えればすぐにフーリエ解析ができるようにしました。
今回の画像は半径1の円

CODE:

double func(double x)
{
	return sqrt(1 - x * x);
}
です。

積分計算にsinなんかが入ってきてますので積分の分割dtが大きくなると発散します。
全体として級数の数nnとdtの積が1.9を超えると発散してしまいます。
以下フーリエ関数クラス(Fourier)と積分関数(integral())のコードです。

CODE:

// Fourier.h
#include 
#include 

static const double PI = 3.1415926535897932384626;

double integral(double (*func)(double x), double dx, double begin, double x, double (*func2)(double x) = 0, double nn = 1);

class Fourier
{
public:
	Fourier(double _T, int _n, double (*_func)(double), double _dx)
		: T(_T), n(_n), func(_func), dx(_dx)
	{
		omg = 2 * PI / T;
		calceff();
	}

	double T;
	double (*func)(double);
	double dx; // used in integral. not eccential for this class.

private:
	int n;
	double omg;
	std::vector an;
	std::vector bn;

public:
	void Setn(int _n)
	{
		n = _n;
		calceff();
	}

	// main
	double calc(double x)
	{
		double sum = 0;

		for(int i = 0; i < n + 1; i++)
		{
			sum += an[i] * cos(i * omg * x) + bn[i] * sin(i * omg * x);
		}

		return sum;
	}

private:

	double a(int m)
	{
		double aa = 2 / T * integral(func, dx, -T / 2, T / 2, cos, m * omg);
		return m ? aa : aa / 2;
	}

	double b(int m)
	{
		return 2 / T * integral(func, dx, -T / 2, T / 2, sin, m * omg);
	}

	void calceff()
	{
		for(int i = 0; i < n + 1; i++)
		{
			an.push_back(a(i));
			bn.push_back(b(i));
		}
	}
};

double integral(double (*func)(double x), double dx, double begin, double x, double (*func2)(double x), double nn)
{
	bool flg = false;
	if(x < begin)
	{
		double tmp = x;
		x = begin;
		begin = tmp;
		flg = true;
	}

	int n = (int)((x - begin) / dx);

	double sum = 0;

	for(int i = 0; i < n; i++)
	{
		if(func2 != 0)
			sum += func(begin + i * dx) * func2((begin + i * dx) * nn) * dx;
		else
			sum += func(begin + i * dx) * dx;
	}

	if(func2 != 0)
		sum += func(begin + dx * n) * func2((begin + dx * n) * nn) * (x - begin - n * dx);
	else
		sum += func(begin + dx * n) * (x - begin - n * dx);

	if(flg)
		sum *= -1;

	return sum;
}
添付ファイル
2011y02m18d_203312215.jpg
2011y02m18d_203312215.jpg (15.29 KiB) 閲覧数: 96 回

コメントはまだありません。