数値を求める課題

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
AC

数値を求める課題

#1

投稿記事 by AC » 9年前

2つのプログラムを用いて、それぞれで1つの値を求める課題なのですが・・・
まず計算式は∫[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;
}
(2)議事乱数を用いた数値積分法
サンプル数を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 );
}

AC

Re: 数値を求める課題

#2

投稿記事 by AC » 9年前

一部おかしな部分がありましたので…
プログラム一つ目の12,13および26行目に入力されている『数値』はそれぞれ何もない状態と考えてください(強いて言うなら12,13行目はそれぞれ-2、3になるとは思うのですが)、その上でお考えいただけると幸いです

かずま

Re: 数値を求める課題

#3

投稿記事 by かずま » 9年前

AC さんが書きました: (1)シンプソン公式による数値積分法
積分区間の分割数を(N=5000)として新婦損公式に夜積分値を求める。
偶数番目の分点は、両端を除くと (N / 2 - 1) 個ですが、
奇数番目の分点は、(N / 2) 個あります。
27行目は、x = a + (2 * k - 1) * dx; でしょう。

AC

Re: 数値を求める課題

#4

投稿記事 by AC » 9年前

なるほど、先ほどまでは32行目を移していたのですが、やはりそうしないといけませんよね、ご指摘ありがとうございます

閉鎖

“C言語何でも質問掲示板” へ戻る