
2次方程式の解を求めるプログラミングの課題なのですが、どのようにすればよいのでしょうか。
プログラミングについてまだまだなので、解説もお願いしたいです。問題は以下のとおりです。
2次方程式ax2+bx+c=0 (a≠0)の係数a,b,c,を入力してその解を表示するプログラムを作成しなさい。2次方程式 の係数a、b、cと解を格納する配列を引数として、2つの異なる実数解を持つ場合は整数1を、重解を持つ場合は整数0を、虚数解を持つ場合は整数-1を戻り値とする関数solveQeを定義して利用すること。解の値は、小数点以下第2位まで表示するものとする。
(注) 平方根を求める関数 double sqrt(double x) の引数xの値は正でなければ エラーとなる。
(実行例)
2次方程式ax^2+bx+c=0の解を求めます
係数a,b,c >> 1,7,9
2つの異なる実数解: -1.70, -5.30
2次方程式ax^2+bx+c=0の解を求めます
係数a,b,c >> 1,8,16
重解: -4.00
2次方程式ax^2+bx+c=0の解を求めます
係数a,b,c >> 2,6,9
虚数解: -1.50 ± 1.50i
(ソースコードイメージ)
#include <stdio.h>
#include <math.h>
int solveQe(int a, int b, int c, double []); //プロトタイプ宣言
int main(void)
{
int a,b,c,d;
double ans[2];
・・・
printf("虚数解: %.2lf ± %.2lf\n",ans[0],ans[1]);
・・・
}
/*
* 2次方程式ax^2+bx+c=0の解
* @引数 係数a,b,c 解m[]
*/
int solveEq(int a, int b, int c, double m[])
{
・・・
}
No.5ベストアンサー
- 回答日時:
あー、うん、C言語慣れてないとメンドくせぇ問題だな、ってのは分かります(笑)。
僕も
「2つの異なる実数解を持つ場合は整数1を、重解を持つ場合は整数0を、虚数解を持つ場合は整数-1を戻り値とする関数solveQeを定義して利用すること」
って文を読んだ時、
「何でやねん。直接解を返さないで何で1、0、-1を返さなアカンねん?」
って初見でそう思いました(笑)。
基本的にモダンな言語のユーザーだと皆同じように思うでしょうね(笑)。「なんてムダなんだ!」と(笑)。これはある意味、C言語らしい問題ですね(笑)。
さて、ポイントは2つあります。
まず一つ目。
今書いたように、問題文の指定だと関数solveQeは「計算する」けど「計算結果」は返さない、と言う不思議な挙動を仕様とします。
つまり、例えばmain関数内で適当な変数dを用意して
d = solveQe(a, b, c, ans);
とした場合、dには何が入るでしょうか?ちょっと考えてみてください。
そうですね、1か0か-1のどれか、です。実は全く計算結果は入らないんです。
言い換えると事実上、2次方程式の解、つまり計算結果は「捨てられてる」って事なんですね。非常に不思議なんですが、これが実はこの問題のポイントなんです。
じゃあ、ここでdは一体何に使われるべきなんでしょうか?答えは一種のフラグなんですね。表示を切り替える「サイン」として働きます。
つまり、問題の要求はmain関数上に次のようなコードを書け、って言ってるんです。
d = solveQe(a, b, c, ans);
if (d > 0)
{
printf("係数a, b, c >> %d, %d, %d\n", a, b, c);
printf("2つの異なる実数解: %.2lf, %.2lf", ans[0] + ans[1], ans[0] - ans[1]);
}
else if (d == 0)
{
printf("係数a, b, c >> %d, %d, %d\n", a, b, c);
printf("重解: %.2lf", ans[0] + ans[1]);
}
else
{
printf("係数a, b, c >> %d, %d, %d\n", a, b, c);
printf("虚数解: %.2lf ± %.2lfi", ans[0], ans[1]);
}
つまり、dの中身によって印字される内容を変えろ、って事です。
「計算上」の話をすると実はsolveQeが行ってる事はこの「切り替え」のサインのみの「返し」で、計算結果自体は全く関係ない、事実上その計算結果「自体」は捨てられてるんです。これが実はこの問題の一つ目のポイントです。
いやちょっと待てよ、と。「計算結果自体が捨てられてるのなら計算結果が見れないじゃん」と思うでしょう。その通りなんですが、もう1つのポイントがC言語特有(でもねぇけどモダンな言語じゃちょっと無い)の性質絡みの事があるんです。
ではその2つ目のポイント。
C言語では別の関数に配列を渡すと基本的に配列の内容を「書き換えてしまう」って特徴があるんですね(正確に言うとC言語だけじゃなくって低レベルの言語だとそう言う事がしばしばある。メモリ効率を優先してるから)。難しい言葉で言うと「副作用」(計算結果が問題にならずに、メモリの状態を書き換えたり、とか印字する「計算自体とは何の関係も無い作用)って言うんですが、このプログラムでは要するにそれが用いられてるわけです。
一般的に昨今のモダンな言語ですと、配列、あるいはリストなんかを別の関数に手渡す場合、大体のケースではそのものを渡さずにコピーを渡すんですね。ところがC言語なんかの低レベル言語だと「データそのものを渡す」ように設計されてて、例えば関数Aから関数Bに配列を渡す、何らかの計算を行って手渡された配列に結果を書き込む(ここが副作用)、そうすると関数Aに戻った時、元あったデータが書き換えられる、って事です(破壊的操作、等と呼んだりします)。
昨今のモダン言語だとこの「破壊的操作」は非常に危険で、データをあっちこっちに手渡した場合、いつ書き換えられるのか、書き換えられた事で元の関数に戻った時にとんでもない挙動が起きたり、とか予測が付かない、ってんで嫌われてるんですが(要するにバグの原因になり得る)、この宿題ではそう言う「破壊的操作」を用いる形式となってるわけです。
solveQe自体は高校数学での「判別式」を知ってればそれほど難しくないです。つまりreturnで「1、0、-1のどれを返すのか」と言うのは判別式に従う、って事ですね。当然if文が活躍します。
int solveQe(int a, int b, int c, double m[2])
{
int determinant = pow(b,2)-4*a*c;
printf("%d\n", determinant);
if (determinant > 0)
{
m[0] = -(double)b/(2*a); // ここが破壊的変更
m[1] = sqrt(determinant)/(2*a); // ここが破壊的変更
return 1; // 返り値
}
else if (determinant == 0)
{
m[0] = -(double)b/(2*a); // ここが破壊的変更
m[1] = sqrt(determinant)/(2*a); // どっちにせよ結果は0
return 0; // 返り値
}
else
{
m[0] = -(double)b/(2*a); // ここが破壊的変更
m[1] = sqrt(-determinant)/(2*a); // ここが破壊的変更
return -1; // 返り値
}
}
もう一度言うと、deteminant(判別式)に従ってif文で返り値を変えます。判別式は高校数学が教えるところの
determinant = b^2 - 4*a*c
ですよね。determinantが0より大きければ実数解、0の時は重解、0より小さければ複素数解になります。
そしてこのコードに於いて、引数で与えられた配列mに「計算結果を書き込む」事が配列への「破壊的変更」で、一旦ここで数値が書き込まれたらどの関数から参照されようと「配列の中身は変わってしまってる」って事です。また、この作用自体は「計算結果を返してる」わけじゃないです(この辺ちょっと難しいかもしれませんが、取り敢えず「データ書き換え」は返り値ではない、つまりsolveQe関数が計算結果自体を返してるわけじゃない、って理解してください)。
もう1つの注意は、僕もちとハマってたんですが(笑)、例えば2次方程式の解を計算する際に
解の一部 = -b/(2*a)
を計算しなければいけませんが、この時点でaもbも整数型ですが、これキチンとbをキャストして型をdoubleとかに変更しないと計算が上手く出来ないんですね(笑)。キャストしないと結果がヘンになるんで、キャストを忘れないようにしましょう。
さて、ここまで書けば、あとはmain関数の方でsolveQe関数の「返り値」を受け取って(つまり結果の1、0、-1に従って)、printfで表示を変えるだけ、ってのが残りの作業です。
この辺はイイですよね。ハナクソです。
int main(void)
{
int a, b, c, d;
double ans[2];
printf("a を入力して下さい: ");
scanf("%d", &a);
printf("b を入力して下さい: ");
scanf("%d", &b);
printf("c を入力して下さい: ");
scanf("%d", &c);
d = solveQe(a, b, c, ans);
if (d > 0)
{
printf("係数a, b, c >> %d, %d, %d\n", a, b, c);
printf("2つの異なる実数解: %.2lf, %.2lf", ans[0] + ans[1], ans[0] - ans[1]);
}
else if (d == 0)
{
printf("係数a, b, c >> %d, %d, %d\n", a, b, c);
printf("重解: %.2lf", ans[0] + ans[1]);
}
else
{
printf("係数a, b, c >> %d, %d, %d\n", a, b, c);
printf("虚数解: %.2lf ± %.2lfi", ans[0], ans[1]);
}
return 0;
}
まあ、こんなモンじゃないでしょうか。
No.4
- 回答日時:
二次方程式は解の公式が分かっていれば解けますよね。
ただ複素数は使わない問題設定のようですので、判別式を使って場合分けして解くことになるでしょう。
また解を受け取ったmain関数の方でも返値で判断して場合分けして表示する必要があるでしょう。
質問中にsolveQeとsolveEqが出てきますが両者は同じものの積もりですか。
関数から解を返すとき、解が虚数になる場合は解を浮動小数点でどのように表すかよく検討してください。
main関数内のprintfの記述がある意味ヒントになっています。
No.1
- 回答日時:
プログラムのことは分かりませんが・・・・
xを0.01ずつ増やしていけば、何処かで関数が0になるか+-が逆転する数があるはずです。
逆転するxをA、Bとすると。
ABの区間をさらに10分の1ずつ増やしていけば必ず解は見つかります。無理数の場合は無限にそれが続くかもしれません
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
今、見られている記事はコレ!
-
弁護士が解説!あなたの声を行政に届ける「パブリックコメント」制度のすべて
社会に対する意見や不満、疑問。それを発信する場所は、SNSやブログ、そしてニュースサイトのコメント欄など多岐にわたる。教えて!gooでも「ヤフコメ民について」というタイトルのトピックがあり、この投稿の通り、...
-
弁護士が語る「合法と違法を分けるオンラインカジノのシンプルな線引き」
「お金を賭けたら違法です」ーーこう答えたのは富士見坂法律事務所の井上義之弁護士。オンラインカジノが違法となるかどうかの基準は、このように非常にシンプルである。しかし2025年にはいって、違法賭博事件が相次...
-
釣りと密漁の違いは?知らなかったでは済まされない?事前にできることは?
知らなかったでは済まされないのが法律の世界であるが、全てを知ってから何かをするには少々手間がかかるし、最悪始めることすらできずに終わってしまうこともあり得る。教えてgooでも「釣りと密漁の境目はどこです...
-
カスハラとクレームの違いは?カスハラの法的責任は?企業がとるべき対応は?
東京都が、客からの迷惑行為などを称した「カスタマーハラスメント」、いわゆる「カスハラ」の防止を目的とした条例を、全国で初めて成立させた。条例に罰則はなく、2025年4月1日から施行される。 この動きは自治体...
-
なぜ批判コメントをするの?その心理と向き合い方をカウンセラーにきいた!
今や生活に必要不可欠となったインターネット。手軽に情報を得られるだけでなく、ネットを介したコミュニケーションも一般的となった。それと同時に顕在化しているのが、他者に対する辛らつな意見だ。ネットニュース...
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
プログラムでの数字につく”f”の...
-
C 開放してるのにエラー(doubl...
-
DWORDの警告
-
テイラー展開(C言語)
-
C言語
-
プログラミングでのテイラー展開
-
c言語 標準体重計算のプログラ...
-
C++初心者です。簡単なスコア計...
-
C言語のpow関数の不具合
-
【C言語】二階微分方程式をル...
-
C言語を実行すると-infが出てき...
-
C言語の複素数についてです。
-
C言語 関数プロトタイプ宣言の...
-
数値を指数部と仮数部に分離したい
-
フロート演算について
-
C言語で関数を使う課題でわかり...
-
3次方程式の求解プログラム(...
-
物体が往復する動きを作りたい
-
プログラミングについて
-
平均を求めるプログラムを作っ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
プログラムでの数字につく”f”の...
-
C 開放してるのにエラー(doubl...
-
至急です! マクロ定義で #defi...
-
C言語を実行すると-infが出てき...
-
C言語の型による処理速度の違い
-
c言語で、繰り返し文の中で、0....
-
C言語 関数プロトタイプ宣言の...
-
doubleの変数にintとintの割り...
-
float型とdouble型の変数の違い...
-
-1.#IND00と出てしまうのですが...
-
c言語のプログラミングについて...
-
C言語で台形公式を使った二重積...
-
C言語でdouble型の小数点の引き...
-
C言語のプログラムで#include<m...
-
2次方程式の解を求めるプログ...
-
doubleは常に%lfとするべきなのか
-
C言語の複素数についてです。
-
difftime()について
-
関数におけるif文とreturn文に...
-
int とdoubleの比較
おすすめ情報