実現したいこと
フーリエ級数展開を行うプログラムをシンプソン積分法により求めましたが、以下のような結果になりました。そのため、パラメータは変えずに誤差を小さくしたいです。
対象関数:y=x*x, x=-10~+10までの周期=20と仮定してます。
(出力:for(double x=0; x<1; x+=0.1))
偶関数なため、sinの計算は0になるので、実装していません。
error(%):-inf error(%):20.0615 error(%):-5.01533 error(%):2.22901 error(%):-1.2538 error(%):0.802411 error(%):-0.557214 error(%):0.409369 error(%):-0.313411 error(%):0.247623 error(%):-0.200564
発生している問題・分からないこと
プログラムに間違いがあるか、誤差はこの程度になるか分からないため、知見がある方に教えて頂きたいです。
該当のソースコード
c++
1#include <iostream> 2#include <cmath> 3#include <math.h> 4 5const int MaxNumOfSeries = 100; // フーリエ級数展開を行う数 6const int HalfPeriod = 10; // 周期の半分 7 8// フーリエ級数展開を行う関数:x*x 9double TargetFunc(double x){ 10 return x*x; 11} 12 13double Fouriercoefficient(double x, int numOfSeries) { 14 return TargetFunc(x) * std::cos(numOfSeries * M_PI* x/ HalfPeriod); 15} 16 17double Simpson(double lowerBound, double upperBound, int divisions, int numOfSeries) { 18 if (divisions % 2 != 0) { 19 divisions++; // nを偶数にする(シンプソンの公式の要件) 20 } 21 22 double h = (upperBound - lowerBound) / divisions; 23 double integral = 0; 24 25 // 積分の開始と終了点を加算 26 integral += Fouriercoefficient(lowerBound, numOfSeries) + Fouriercoefficient(upperBound, numOfSeries); 27 28 // 各小区間においてシンプソンの公式を適用 29 for (int i = 1; i < divisions; i += 2) { 30 integral += 4 * Fouriercoefficient(lowerBound + i * h, numOfSeries); // 奇数インデックスの項 31 } 32 33 for (int i = 2; i < divisions; i += 2) { 34 integral += 2 * Fouriercoefficient(lowerBound + i * h, numOfSeries); // 偶数インデックスの項 35 } 36 37 // 最後に h / 3 を掛けて積分結果を計算 38 integral *= h / 3; 39 return integral; 40} 41 42double FourierSeries(double x){ 43 double lowerBound = -HalfPeriod; // 積分の下限 44 double upperBound = HalfPeriod; // 積分の上限 45 int divisions = 5000; // 分割数 46 47 double sum = Simpson(lowerBound, upperBound, divisions,0)/(2* HalfPeriod); // 級数=0を加算 48 49 // 0以外の級数展開を計算 50 for(int i= 1; i<= MaxNumOfSeries; i++){ 51 sum+= Simpson(lowerBound, upperBound, divisions, i)/HalfPeriod * std::cos(i *M_PI *x/ HalfPeriod); 52 } 53 54 return sum; 55} 56 57int main() { 58 59 for(double x=0; x<1; x+=0.1){ 60 // std::cout << "x= " << x << " x*x= " << TargetFunc(x) << " FourierSeries= " << FourierSeries(x) << std::endl; 61 std::cout <<"error(%):" << (TargetFunc(x) - FourierSeries(x))/TargetFunc(x) *100 << std::endl; 62 } 63 64 return 0; 65} 66
試したこと・調べたこと
- teratailやGoogle等で検索した
- ソースコードを自分なりに変更した
- 知人に聞いた
- その他
上記の詳細・結果
シンプソン積分法の誤差は以下のサイトに書いてあり、そうすると今回の誤差は0.1%以上もあるのは大きいように感じています。
補足
特になし
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。