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

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

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

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

Q&A

解決済

5回答

3117閲覧

積分の台形近似について

kentashx

総合スコア15

C

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

1グッド

0クリップ

投稿2016/04/25 02:22

###前提・実現したいこと
xxxの0から2までの定積分を求めるプログラムを台形の面積で近似して求めたいです。
###発生している問題・エラーメッセージ
n=1,ans=8.000000
n=2,ans=5.000000
n=3,ans=0.000000
n=4,ans=0.000000
以下ansが全て0になってしまいます。

どうしてansが0になってしまうのかが分かりません。また、どのように解決すればいいのか分かりません。

###該当のソースコード
#include <stdio.h>

//f(x):関数
//a:積分範囲の下限値
//b:積分範囲の上限値
//n:台形の分割数
//x1:分割した台形の左端のx座標
//x2:分割した台形の右端のx座標
//h:分割した台形の高さ
//ans:求める値

#define f(x) xxx
#define a 0
#define b 2

float traArea(float y1,float y2,float h){ //台形の面積を求める関数のプロトタイプ宣言
return (y1+y2)*h/2;
}

int main(){
int n,i; //i,nは整数なのでint型で宣言する
float h,x1,x2,ans; //x1,x2,y1,y2,ansは小数になるのでfloat型で宣言する
printf("何分割しますか?"); //分割する台形の個数を指定する
scanf("%d",&n); //キーボードから入力
h=(b-a)/n;
ans=0.0;

for(i=0;i<n;i++){ x1=a+i*h; //i個目の台形の左端のx座標 x2=x1+h; //i個目の台形の右端のy座標 ans+=traArea(f(x1),f(x2), h); //i個目の台形の面積を(i-1)個目までの台形の面積の総和に加える } printf("求める積分値は%fです。",ans); return 0;

}

###試したこと
どうしてn=3以降ansが0になってしまうのかさっぱり分かりません。

###補足情報(言語/FW/ツール等のバージョンなど)
C言語、XcodeのVersion7.3で実行しました。

KiyoshiMotoki👍を押しています

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2016/04/25 02:37

ソースコード貼り付けた際,#がつくところは見出し文になります. コード部はコードタグで書いていただけると助かります.
kentashx

2016/04/25 02:51

指摘ありがとうございます!! 投稿初めてなもので、よくわかっていませんでした。 この質問は解決したので次回の投稿時には参考にさせてもらいます。
退会済みユーザー

退会済みユーザー

2016/04/25 03:05

ちなみにコードタグってのは </> とアイコンが付いたやつです.これに挟まれていると回答にもありますが,コードが見やすくなりますので確認してみてください.
guest

回答5

0

既に解決していますが、参考情報を書きます。

デバッグ用の print 文を入れれば、台形の計算に使うパラメータが いつも 0 になってしまっていたことがわかったはずです。
それに気がつけば、割り算のことに気が付いたと思います。

c

1float traArea(float y1,float y2,float h) { 2 printf("%f, %f, %f => %f\n", y1, y2, h, (y1+y2)*h/2); 3 return (y1+y2)*h/2; 4}

デバッグ文を入れたり、使う変数の数をなるべく少なくしてみたコードを↓に示します。

c

1 2#include <stdio.h> 3 4//f(x):関数 5//a:積分範囲の下限値 6//b:積分範囲の上限値 7#define f(x) ((x) * (x) * (x)) 8// #define f(x) x*x*x 9#define a (0.0) 10#define b (2.0) 11 12float traArea(float y1, float y2, float h) { // 台形の面積を求める関数のプロトタイプ宣言 13 printf("-- %f, %f, %f ==> %f\n", y1, y2, h, (y1 + y2) * h / 2); 14 return (y1 + y2) * h / 2; 15} 16 17int main() { 18 int n; // i, nは整数なのでint型で宣言する 19 printf("何分割しますか?"); // 分割する台形の個数を指定する 20 scanf("%d", &n); // キーボードから入力 21 22 float ans = 0.0; // ans, h は小数になるのでfloat型で宣言する 23 float dx = (b - a) / n; // 1つの台形の幅 (x 座乗の差) 24 25 for (int i = 0; i < n; i++) { 26 // a + i * dx i個目の台形の左端のy座標 27 // a + (i + 1) * dx i個目の台形の右端のy座標 28 ans += traArea(f(a + i * dx), f(a + (i + 1) * dx), dx); // i個目の台形の面積を(i-1)個目までの台形の面積の総和に加える 29 } 30 printf("求める積分値は%fです。\n",ans); 31 return 0; 32}

上で #define f(x) ((x) * (x) * (x))としているのは重要です。
#define f(x) xxx としていると
f(a+b) のような呼び出しは
a + b * a + b * a + b
と展開されてしまいます。
((x) * (x) * (x)) と定義すれば、
(a + b) * (a + b) * (a +b)
と展開されます。

投稿2016/04/25 22:11

katoy

総合スコア22324

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

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

kentashx

2016/04/26 01:30

デバッグでprintfを使えば気づけたのですね.なるほど. マクロの定義も()をつけた方が良さそうですね. 修正したコード,とてもすっきりしていて読みやすいです.すっきりしたコードを書けるように練習していきます.
guest

0

ベストアンサー

h=(b-a)/n;のところで、右辺に現れるものが全て整数なので、割り算の時点で切り捨てられて0となっています。

h=(b-a)/(float)nとして、右辺でも浮動小数として計算させましょう。

あと、ぜんぜん関係ない点ですが、気になることが何点かあります。

  • #defineした定数は、全て大文字で書くのが慣習となっています(ふつうの変数などとの衝突を避けるためもあります)。
  • f(x)をマクロとして定義していますが、f(2+3)とかf(i++)などを展開すると、想定外の展開がなされてしまいます。素直に関数としましょう。
  • DSPや組み込みなどで特に単精度とする必要がある状況でなければ、floatよりdoubleを使ったほうがいいです。

投稿2016/04/25 02:34

maisumakun

総合スコア145123

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

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

kentashx

2016/04/25 02:42

なるほど、確かに右辺は全て整数なので切り捨てられてしまいますね。 すっかり見落としてました。非常に参考になりました。修正したら正しい値が出力されるようになりました。ありがとうございます!!!! その他の部分も知らなかったのですが、非常に参考になりました。 初心者なのでどんどん知らない部分を吸収していきます!!!
guest

0

整数が切り捨てられることをすっかり見落としてました。
nを浮動小数とすることで解決しました。

投稿2016/04/25 02:48

kentashx

総合スコア15

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

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

0

c

1 h = (b-a)/(float)n; 2 3```とするか 4```c 5#define a 0.0f 6#define b 2.0f 7

とすればいいと思います。
hがintで計算した結果になっているため入力されたnがb-aつまり2よりも大きい値になると結果が0になってしまう事が原因だと思われます。

投稿2016/04/25 02:39

HiroshiWatanabe

総合スコア2160

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

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

kentashx

2016/04/25 02:44

切り捨てられることをすっかり見落としてました。 ありがとうございます!!!!
guest

0

a,bを0, 2でなく
0.0, 2.0 と定義しないと(b-a)/nが整数演算されてしまいます。

投稿2016/04/25 02:36

yuba

総合スコア5568

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

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

kentashx

2016/04/25 02:47

すっかり見落としてました。 nを浮動小数とすることで解決しました。 ありがとうございます!!!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問