質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

MacOS(OSX)

MacOSとは、Appleの開発していたGUI(グラフィカルユーザーインターフェース)を採用したオペレーションシステム(OS)です。Macintoshと共に、市場に出てGUIの普及に大きく貢献しました。

Q&A

1回答

2742閲覧

C言語で表のように結果を出力したい

reoreoni

総合スコア0

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

MacOS(OSX)

MacOSとは、Appleの開発していたGUI(グラフィカルユーザーインターフェース)を採用したオペレーションシステム(OS)です。Macintoshと共に、市場に出てGUIの普及に大きく貢献しました。

0グッド

0クリップ

投稿2021/12/12 15:10

「次の関数の x = 0.0 ~ 1.0 における積分計算を,台形則 およびシンプソン則を用いて実施せよ.
y = e^x * cosx
ただし,積分領域の分割数を「2, 4, 8, 16, 32, 64, 128, 256, 512, 1024」の10通りとし
それぞれの場合の積分値を求めるとともに,それらと厳密解を比較し誤差(実誤差)を計算せよ
さらに得られた誤差の値が,分割数を倍にするたびに台形則においては約1/4に,シンプソン則においては約1/16に減少していることを確認せよ」

この問題で分割数を一つずつ変更して結果と誤差を得ることができるプログラムは作れたのですが、出力したい結果
上の写真のように分割数を全て一回で計算して、全部の情報をまとめて表のように出力したいです。

今できているコードは以下のものです。
今かけているコード
kadai1.cが台形則による計算で、kadai2.cがシンプソン則による計算です。

まだまだC言語を勉強中なので、いろいろ教えていただけると幸いです。
よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

分割数を一つずつ変更して結果と誤差を得ることができるプログラムは作れた

その処理を関数化して、複数回呼び出してあげれば良いかと思います。

■ 処理のイメージ
イメージ説明

■ コード例

C

1#include <stdio.h> 2#include <math.h> 3 4#define f(x)(exp(x) * cos(x)) 5 6void calcTrapezoidalRule(int m); 7 8int main() { 9 int i; 10 int m; 11 // 表のヘッダ部 12 printf("分割数 数値積分値 誤 差\n\n"); 13 for (i = 0; i < 10; i++) { 14 m = (int)pow(2, i+1); 15 calcTrapezoidalRule(m); 16 } 17 18 return 0; 19} 20 21void calcTrapezoidalRule(int m) { 22 int i; 23 double a = 0.0, b = 1.0; 24 double h, S; 25 double x = 0.0, sum = 0.0; 26 double y0, ym; 27 double cor, err; 28 29 y0 = f(a); 30 ym = f(b); 31 h = (b - a) / m; 32 for (i = 1; i < m; i++){ 33 x = a + i * h; 34 sum += f(x); 35 } 36 37 S = (y0 + ym + 2.0 * sum) * h / 2.0; 38 39 cor = exp(b)*(sin(b) + cos(b)) / 2.0 - exp(a) * (sin(a) + cos(a)) / 2.0; 40 err = fabs(S - cor) / cor * 100.0; 41 42 // 表のデータ部 43 printf("%5d %1.15f %1.15f\n", m, S, err); 44}

■ 実行結果

分割数 数値積分値 誤 差 2 1.340618003271056 2.714509589202056 4 1.368582382531060 0.685200461840610 8 1.375658434900208 0.171708010429835 16 1.377432718220980 0.042952449511029 32 1.377876617809296 0.010739702078779 64 1.377987613243850 0.002685024864576 128 1.378015363385925 0.000671262425028 256 1.378022301001658 0.000167815994236 512 1.378024035410606 0.000041954022616 1024 1.378024469013152 0.000010488507298

ちなみに想定結果と誤差の値が違っているようでした。課題のようですので、原因について調べてみて下さい。
それと、「前の誤差との比」も出力していません。
戻り値を void にしているか箇所を計算結果を返すようにして、次回実行時にその結果を引き継ぐようにすれば、出力できるかと思います。

投稿2021/12/12 15:57

編集2021/12/13 13:16
cx20

総合スコア4648

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

reoreoni

2021/12/13 07:15

cx20さんアドバイスありがとうございます! コードを変えて誤差を正しく表示させることができたのですが voidの使い方が調べても分からず、 前との誤差との比が全て1.0になってしまいます。 voidを使うやり方も是非教えていただきたいです! 書き換えたコードは以下のものです #include <stdio.h> #include <math.h> #define f(x)(exp(x) * cos(x)) void calcTrapezoidalRule(int m); int main() { int i; int m; // 表のヘッダ部 printf("分割数 数値積分値 誤 差 前の誤差との比\n\n"); for (i = 0; i < 10; i++) { m = (int)pow(2, i+1); calcTrapezoidalRule(m); } } void calcTrapezoidalRule(int m) { int i; double a = 0.0, b = 1.0; double h, S; double x = 0.0, sum = 0.0; double y0, ym; double cor, gosa, gosahi; y0 = f(a); ym = f(b); h = (b - a) / m; for (i = 1; i < m; i++){ x = a + i * h; sum += f(x); } S = (y0 + ym + 2.0 * sum) * h / 2.0; cor = exp(b)*(sin(b) + cos(b)) / 2.0 - exp(a) * (sin(a) + cos(a)) / 2.0; gosa = cor - S; gosahi = gosa / gosa; // 表のデータ部 printf("%5d %1.15f %1.15f %1.15f\n", m, S, gosa, gosahi); } 出力結果は以下のものです 分割数 数値積分値 誤 差 前の誤差との比 2 1.340618003271056 0.037406610276308 1.000000000000000 4 1.368582382531060 0.009442231016304 1.000000000000000 8 1.375658434900208 0.002366178647156 1.000000000000000 16 1.377432718220980 0.000591895326383 1.000000000000000 32 1.377876617809296 0.000147995738067 1.000000000000000 64 1.377987613243850 0.000037000303514 1.000000000000000 128 1.378015363385925 0.000009250161438 1.000000000000000 256 1.378022301001658 0.000002312545706 1.000000000000000 512 1.378024035410606 0.000000578136758 1.000000000000000 1024 1.378024469013152 0.000000144534212 1.000000000000000
cx20

2021/12/13 16:12

> voidの使い方が調べても分からず、 void は関数の戻り値が無いことを表すキーワードになります。 つまり、現状は、calcTrapezoidalRule() 関数は、戻り値を返していない、ということです。 関数で戻り値を返す場合は「return xxx;」といった書き方になります。 まずは、戻り値を返すようにしてみて下さい。 前回との誤差を比較する必要があるので、戻り値として「誤差」を返すようにしてみて下さい。 変更前)void calcTrapezoidalRule(int m); 変更後)double calcTrapezoidalRule(int m); … 戻り値として、誤差を返却するよう対応 使い方としては、 lastError = calcTrapezoidalRule(m); といった使い方になると思います。 ただ、これだと、前の誤差との比較が行えない為、さらに拡張をします。 変更後)double calcTrapezoidalRule(int m, double lastError); … 引数に「前回の誤差」を追加 使い方としては、 lastError = calcTrapezoidalRule(m, lastError); といった感じになると思います。 そうすると、calcTrapezoidalRule() の中で、「前回の誤差」と「今回の誤差」が取得できるので、 「前の誤差との比」が求めることができるかと思います。 > 前との誤差との比が全て1.0になってしまいます > gosahi = gosa / gosa; よく目を凝らして見て下さい。同じ値で割ったら、1.0 になるのは当然かと・・
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問