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

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

ただいまの
回答率

90.47%

  • C

    3834questions

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

積分の台形近似について

解決済

回答 5

投稿

  • 評価
  • クリップ 0
  • VIEW 903

kentashx

score 8

前提・実現したいこと

x*x*xの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) x*x*x

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で実行しました。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • 退会済みユーザー

    退会済みユーザー

    2016/04/25 11:37

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

    キャンセル

  • kentashx

    2016/04/25 11:51

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

    キャンセル

  • 退会済みユーザー

    退会済みユーザー

    2016/04/25 12:05

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

    キャンセル

回答 5

checkベストアンサー

+1

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

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

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/04/25 11:42

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

    キャンセル

+1

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

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

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


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

#include <stdio.h>

//f(x):関数
//a:積分範囲の下限値
//b:積分範囲の上限値
#define f(x) ((x) * (x) * (x))
// #define f(x) x*x*x
#define a (0.0)
#define b (2.0)

float traArea(float y1, float y2, float h) {  // 台形の面積を求める関数のプロトタイプ宣言
  printf("-- %f, %f, %f ==> %f\n", y1, y2, h, (y1 + y2) * h / 2);
  return (y1 + y2) * h / 2;
}

int main() {
  int n;                      // i, nは整数なのでint型で宣言する
  printf("何分割しますか?"); // 分割する台形の個数を指定する
  scanf("%d", &n);            // キーボードから入力

  float ans = 0.0;           // ans, h は小数になるのでfloat型で宣言する
  float dx = (b - a) / n;    // 1つの台形の幅 (x 座乗の差)

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/04/26 10:30

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

    キャンセル

0

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/04/25 11:47

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

    キャンセル

0

h = (b-a)/(float)n;

とするか

#define a 0.0f
#define b 2.0f


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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/04/25 11:44

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

    キャンセル

0

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

関連した質問

  • 解決済

    ブランク(空白)列をタブに置き換えるには?

    **問題 「ブランクの列を同じスペーシングを行う最小の数のタブおよびブランク  で置き換えるプログラムentabを書け。」 にとりくんでいます。 下のようにプログラムを作ってみたの

  • 解決済

    C言語プログラムが思うように動きません

    c言語でコードを書きましたが、コンパイルしたところ何も起きません どこが間違っているのか教えてください。 コード#include<stdio.h> double power(do

  • 解決済

    皆様のお答えを聞かせてください。打ちこんだ整数を逆に並べて出力する

    このコードはマイナスの値を打つと、アラームが鳴り整数値を打つように 指示します。そして整数値が打ちこまれると、それを10で割り余りを出す、10で割るという繰り返しで引っくり返した数

  • 解決済

    データを整理する際の二次元配列

    2つの変数に対応するデータがある時、二次元の配列にしたいのですが、2つの変数の関数として出る値ではないため、どのようにしたらいいか困っております。 例として、 x     y   

  • 解決済

    c言語 等比数列

    解決済 ここまで書いたのですが意味不明な数字がでます。 #include<stdio.h> int main(void) {     int i,n;     double a,

  • 受付中

    C言語における2乗関数、3乗関数の作成について

    main関数から入力された数値の2乗、3乗を計算し、それぞれ表示する関数を作りたいです。 標準関数のpowは使いたくないです。 要は、乗算を2回、乗算を3回という形でのコードをか書

  • 解決済

    printf関数に関する疑問

    前提・実現したいこと c言語の初心者です。printf関数について質問です。 発生している問題・エラーメッセージ 以下のコードを実行した際想像とは違った結果になったため質問させ

  • 解決済

    C言語でわからないこと

    include <stdio.h> float calc(char op, float a, float b); main(){ float number; number 

同じタグがついた質問を見る

  • C

    3834questions

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