ある関数


区間





また、各分点の幅は h とします。

関数



前述の積分を行うために








係数 C の各項は展開するとわかるとおり、n 次多項式になっています。従ってすべての項を足しても n 次多項式です。これは n + 1 点からなる点列を n 次式で近似することによって面積を求めていることに他なりません。つまり、2 点からなる点列なら 1 次式(直線)で近似し、3 点からなる点列なら 2 次式で近似させるわけです。
次数 n が低ければ直接求めることができます。
次数 n が 1 のときを特に




次数 n が 2 のときを特に




一般的にはこのシンプソンの公式がよく使われます。
シンプソンの公式のように2次以上の n 次式で近似する場合、分割数が n の倍数(分点数が n の倍数プラス 1)でなければなりません。そうでなければ、残った部分は切り捨てたり、そこだけ n 次未満で求めるなどの工夫が必要でしょう。
// ver.041107
#ifndef __NEWTON_COTES_H
#define __NEWTON_COTES_H
#include <vector>
// y データの列
// h データの間隔
// n 次数(n=1 なら台形公式、n=2 ならシンプソンの公式、1 <= n <= 5 に対応)
double NewtonCotes(std::vector<double> &y, double h, long n)
{
if(n < 1) n = 1;
if(n > 5) n = 5;
static bool isFirst = true;
static double cTable[6][6]; //[0][] は未使用
if(isFirst){
cTable[1][0] = 1.0 / 2.0;
cTable[1][1] = 1.0 / 2.0;
cTable[2][0] = 1.0 / 3.0;
cTable[2][1] = 4.0 / 3.0;
cTable[2][2] = 1.0 / 3.0;
cTable[3][0] = 3.0 / 8.0;
cTable[3][1] = 9.0 / 8.0;
cTable[3][2] = 9.0 / 8.0;
cTable[3][3] = 3.0 / 8.0;
cTable[4][0] = 14.0 / 45.0;
cTable[4][1] = 64.0 / 45.0;
cTable[4][2] = 24.0 / 45.0;
cTable[4][3] = 64.0 / 45.0;
cTable[4][4] = 14.0 / 45.0;
cTable[5][0] = 95.0 / 288.0;
cTable[5][1] = 375.0 / 288.0;
cTable[5][2] = 250.0 / 288.0;
cTable[5][3] = 250.0 / 288.0;
cTable[5][4] = 375.0 / 288.0;
cTable[5][5] = 95.0 / 288.0;
isFirst = false;
}
int m = (int)y.size() - 1; //分割数
double s = 0;
long k, i;
for(k = 0; k <= m / n - 1; k++){
for(i = 0; i <= n; i++){
s += cTable[n][i] * y[n * k + i];
}
}
//端数部分の計算
int lastBlockStart = n * k;
int lastBlockEnd = (int)y.size() - 1;
m = lastBlockEnd - lastBlockStart;
n = m;
if(m > 0){
for(i = 0; i <= n; i++){
s += cTable[n][i] * y[lastBlockStart + i];
}
}
return h * s;
}
#endif
#include <iostream>
#include <cmath>
#include <vector>
using namespace std;
#include "../NewtonCotes.h"
main()
{
vector<double> y;
double h = 0.01;
for(int i = 0; i < 314; i++){
y.push_back(sin(i * h));
}
cout << NewtonCotes(y, h, 2) << endl;
return 0;
}