まず計算式は∫[exp(cos( 0.2 * x + 1 )) + sqrt(2 + sin(x) * cos(2 * x))]dx(積分範囲は-2<x<3)です
そのことを踏まえて以下のプログラムで積分値を求めるものなのですが、それぞれの課題でいまいちどこが足りないのか、どんな数値を入力すればよいのかがよくわかりません、ご指摘いただけると幸いです
(1)シンプソン公式による数値積分法
積分区間の分割数を(N=5000)として新婦損公式に夜積分値を求める。
/* シンプソン公式による数値積分の計算精度 */
#include <stdio.h>
#include "glibw32.h"
double f( double x );
int main ( void )
{
int k, N;
double s, s_odd, s_even, dx, x, a, b, error, s_exact;
a = 0.0; /* 積分範囲[a,b]の設定 */
b = 1.0; /* 積分範囲[a,b]の設定 */
N = 5000; /* 積分区間の分割数の設定 */
dx = ( b - a ) / (double) N; /* 積分区間のきざみ幅 */
printf( "積分区間: [a,b] = [%f, %f]\n", a, b );
printf( "分割数: N = %d\n", N );
printf( "きざみ幅: dx = %e log10(dx) = %f\n", dx, log10( dx ) );
/* シンプソン公式による数値積分 */
s = f( a ) + f ( b ); /* シンプソン公式による数値積分値sの初期値(端点での値) */
s_odd = 0.0; /* 奇数番目の分点の値の和の初期値 */
for( k = 1; k <= N/2-1 ; k++ ) {
x = ; /* 奇数番目の分点 */
s_odd += f( x ); /* シンプソン公式(奇数番目の分点の値の和) */
}
s_even = 0.0; /* 端点を除く偶数番目の分点の値の和の初期値 */
for( k = 1; k <= N/2-1 ; k++ ) {
x = a + 2 * k * dx; /* 偶数番目の分点 */
s_even += f( x ); /* シンプソン公式(端点を除く偶数番目の分点の値の和) */
}
s = ( s + 4.0 * s_odd + 2.0 * s_even ) * dx / 3.0;
s_exact = exp( 1.0 ) - 1.0; /* 定積分の正確な値 */
printf( "積分値: シンプソン公式 = %.15e\n 正確な値 = %.15e\n", s, s_exact );
error = fabs( s - s_exact ); /* 計算誤差 */
printf( "計算誤差: ΔS = %e log10(ΔS) = %f\n", error, log10( error ) );
return 0;
}
/* 被積分関数f(x)の定義 */
double f( double x )
{
double r;
r = exp(cos( 0.2 * x + 1 )) + sqrt(2 + sin(x) * cos(2 * x));
return r;
}
サンプル数をN=3000とした議事乱数を用いて積分値を求める
#include <stdio.h>
#include <stdlib.h> /* 乱数を発生させる関数rand、srandを利用するために必要なヘッダファイル */
#include "glibw32.h"
#define N 30000 /* サンプル数(的当ての回数 ) */
double f( double x ); /* 被積分関数 */
int main ( void )
{
int m, n;
double a, b, x, y, ymax, s;
/* グラフ描画の初期設定 */
ginit( 600, 400, WHITE ); /* 幅600、高さ400の白色背景のウィンドウを表示 */
GRAPH g1; /* クラスGRAPHのインスタンスg1を生成する */
g1.view( 20, 20, 580, 380 ); /* g1にウィンドウの左上(20,20)から右下(580,380)の範囲をスクリーン座標系として描画 */
g1.window( -1, -0.5, 7, 3 ); /* g1に論理座標系を設定 */
g1.axis( 1.0, 1.0 ); /* g1に座標軸をプロット */
g1.textout( -0.5, -0.2, "0"); /* g1に原点をプロット */
g1.textout( 6.5, -0.2, "x"); /* g1のx軸に「x」とプロット */
g1.textout( 1.0, -0.2, "1"); /* g1のx軸に「1」とプロット */
g1.textout( 5.0, -0.2, "5"); /* g1のx軸に「5」とプロット */
g1.textout( -0.5, 2.5, "y"); /* g1のy軸に「y」とプロット */
g1.textout( -0.5, 1, "1"); /* g1のy軸に「1」とプロット */
g1.textout( -0.5, 2, "2"); /* g1のy軸に「2」とプロット */
a = 3.0; /* 積分範囲[a,b]の設定 */
b = -2.0; /* 積分範囲[a,b]の設定 */
ymax = 2.0; /* ymaxの設定 */
printf( "---<< 擬似乱数を用いた数値積分法 >>---\n" );
printf( "積分範囲:[a, b] = [%f, %f]\n", a, b );
printf( "ymax = %f\n\n", ymax );
m = 0; /* 点(x,y)があたりである回数を数えるカウンタ */
for( n = 0; n < N; n++ ) { /* 的当てをN回繰り返す */
x = (double) rand( ) / RAND_MAX; /* xに区間[0,1]上の実数値一様乱数を代入 */
x = a + ( b - a ) * x; /* xを区間[a,b]上の実数値一様乱数に変換 */
y = (double) rand( ) / RAND_MAX; /* yに区間[0,1]上の実数値一様乱数を代入 */
y = ymax * y; /* yを区間[0,ymax]上の実数値一様乱数に変換 */
if( y < f( x ) ) { /* もし点(x,y)があたりであれば */
m++; /* カウンタmを1増やす */
g1.disk( x, y, 2, 1, RED ); /* グラフ:点(x,y)に赤●を描画する */
}
else { /* もし点(x,y)がはずれであれば */
g1.disk( x, y, 2, 1, BLUE ); /* グラフ:点(x,y)に青●を描画する */
}
}
printf( "%d回のうち点(x,y)があたりである回数は%d回です\n", N, m);
s = m * ( b - a ) * ymax / (double) N; /* 定積分の近似値 */
printf( "定積分の近似値:s = %.15f\n", s );
x = -0.5;
g1.moveto( x, f( x ) ); /* グラフ:現在位置を点(-0.5,f(-0.5))に移動 */
for( x = -0.5; x < 6.5; x += 0.05 ) { /* 関数y=f(x)の描画 */
g1.lineto( x, f( x ), BLACK ); /* グラフ:現在位置から点(x,f(x))まで黒い線を引く */
}
gend( ); /* グラフィックスの終了 */
return 0;
}
/* 被積分関数f(x)の定義 */
double f( double x )
{
double r;
r = exp(cos( 0.2 * x + 1 )) + sqrt(2 + sin(x) * cos(2 * x));
return( r );
}