このページでは、C言語で複数の値から「最大値・最小値」を求める方法について解説していきます。
C言語では、他の言語とは異なり、max
や min
といった最大値・最小値を求める関数が標準では用意されていません。
処理系によっては用意されている場合があるようですが、用意されていない場合は自身で最大値や最小値を求める必要があります(私は MacOSX を使用していますが、max
・min
は用意されていないようでした)。
ただ、最大値や最小値を求めるのは簡単なので、自身で求めるとしてもそこまで負担にはならないと思います。
ということで、このページでは最大値や最小値を求める方法について解説していきます。
Contents
2つの値の最大値を求める
最大値や最小値を求める上で一番基本になるのは、この「2つの値から最大値を求める」処理になると思います。
ただ、求め方は単純で、2つの値を比較演算子で比較して「大きい方の値」を最大値としてやれば良いだけです。
2つの値の最大値を求める関数
例えば下記は、2つの値の最大値を求める関数の例となります。
int maxValue(int num1, int num2) {
int max_value; /* 最大値 */
/* 2つの値を比較して大きい方を最大値とする */
if (num1 > num2) {
max_value = num1;
} else {
max_value = num2;
}
return max_value;
}
上記では2つの引数 num1
と num2
の比較を行って大きい方の値を max_value
に格納し、その max_value
を最大値として返却するようにしています。
もし2つの値が同じである場合、どちらの値を最大値として選んだとしても結果は同じになります。
上記では num1 == num2
の場合に num2
が最大値となるようにしていますが、num1 > num2
の部分を num1 >= num2
に変更すれば、num1 == num2
の場合に num1
が最大値となるようになります。
ただし、前述のように両方同じ値なのですから、いずれにしても正しく最大値を求めることができます。
スポンサーリンク
2つの値の最大値を求める関数(float
)
上記の maxValue
関数は int
型の2つの値から最大値を求める関数の例となります。
当然最大値は他の型の値でも求めることが可能であり、上記の maxValue
関数も型さえ変更してやれば “他の型の2つの値から最大値を求める関数” に変更することが可能です。
例えば float
型の2つの値から最大値を求める関数は、次のように上記の maxValue
関数の “返却値の型” と “比較対象となる引数の型” および “最大値を扱う変数の型” を float
に変更するだけで実現することができます。
float maxValue(float num1, float num2) {
float max_value; /* 最大値 */
/* 2つの値を比較して大きい方を最大値とする */
if (num1 > num2) {
max_value = num1;
} else {
max_value = num2;
}
return max_value;
}
以降で紹介する関数についても同様ですので、最大値を求めたい値の型に応じて適宜変更していただければと思います。
2つの値の最大値を求める関数(3項演算子)
また、最初にお見せした maxValue
関数は3項演算子を利用すれば下記のように簡潔に表すことも可能です。
int maxValue(int num1, int num2) {
return (num1 > num2) ? num1 : num2;
}
2つの値の最小値を求める
最大値を求める時とは逆に、最小値を求める際には2つの値を比較して「小さい方の値」を最小値として返却するようにします。
int minValue(int num1, int num2) {
int min_value; /* 最小値 */
/* 2つの値を比較して小さい方を最小値とする */
if (num1 < num2) {
min_value = num1;
} else {
min_value = num2;
}
return min_value;
}
関数名や変数名、さらにはコメントは異なるものの、2つの値の最大値を求める の最初で紹介した maxValue
関数と実質的に処理が異なるのは「比較実行部分のみ」です
具体的には、maxValue
関数で比較演算子に >
を使用していたところを maxValue
関数では <
を使用するように変更しただけです。
つまり、最小値を求める関数やプログラムは、最大値を求める関数やプログラムから “比較演算子を変更さえすれば実現可能” ということです。
これは2つの値から最大値・最小値を求める時に限った話ではなく、以降で解説する「配列の中から最大値を求める」場合においても同様です。ですので、説明の重複を避けるため、今後は最大値に関する解説のみを行うものとさせていただきます。
最小値を求めたい場合は、紹介する関数で使用している比較演算子を >
から <
に変更してください(>=
を使用している箇所は <=
に変更してください)。これにより、最小値を求める関数を実現することが出来ます。
スポンサーリンク
配列の中から最大値を求める
次は配列の中から最大値を求めていきたいと思います!
配列の中から最大値を求める関数
C言語においては、3つ以上の値を同時に比較することはできません。
そのため、ループ処理の中で、その時点の最大値と配列の要素の値を1つ1つ比較をしていく必要があります。
具体的には、下記の関数 maxValue
により、サイズ n
の配列 nums
の全要素から最大値を求めることができます。
int maxValue(int nums[], int n) {
int max_value; /* 最大値 */
int i;
/* nums[0]を最大値と仮定する */
max_value = nums[0];
for (i = 0; i < n; i++) {
if (nums[i] > max_value) {
/* 最大値よりもnums[i]の方が大きければ最大値を更新 */
max_value = nums[i];
}
}
return max_value;
}
n
が 0
以下の場合はうまく動作しないので注意してください(配列外にアクセスしてしまう)。
maxValue
関数でやってる処理は簡単で、配列の先頭の値が最大値であると仮定し、その最大値よりも大きい値を見つける度に最大値を更新していくことで最大値を求めています。
具体的には、まず配列の先頭の値が最大値であると仮定し、max_value = nums[0]
を行なっています。この max_value
は最大値を格納するための変数になります。
以降は、ループ処理の中で配列の先頭から各要素の値 nums[i]
と max_value
の比較を行い、nums[i]
が max_value
よりも大きな値であった場合、max_value
は最大値ではなかったということになりますので、max_value = nums[i]
を行なって最大値を nums[i]
に更新します。
もちろん、nums[i]
が max_value
以下の値の場合は max_value
が最大値である仮定は崩れていないので、max_value
の更新を行う必要はありません。
あとは上記のように max_value
よりも大きな値を見つけるたびに max_value
の更新を行っていけば、配列の末尾まで同様の処理が完了したタイミングで max_value
には配列全体の中の最大値が格納されていることになります。
これにより配列 nums
の中の最大値 max_value
が求まったことになります。
ちなみに、maxValue
関数の for
ループでは i
を 0
から開始していますが、i
が 0
の場合は nums[i] > max_value
は絶対に成立しないことが分かりきっているため、i
は 1
から開始するのでも問題ありませんん。
また、上記の maxValue
関数内で使用している比較演算子 >
を >=
に変更したとしても、最大値は正しく求めることが出来ます。
ですので、単に最大値を求めたいのであればどちらの比較演算子を使用しても問題ありません。
ただ、下記ページのように「最大値の持つ要素の添字」を求める際には、どちらの比較演算子を用いるかによって結果が異なることになるので注意してください。
【C言語】配列の中から最大値を持つ要素の”添字”を求める配列の中から最大値を求める際の注意点
前述で説明した for
ループ内の処理自体は単純だと思いますが、下記の処理を忘れないように注意が必要です。
/* nums[0]を最大値と仮定する */
max_value = nums[0];
不定値との比較を行わないように注意
for
ループの先頭で max_value
と nums[i]
の比較を行なっているので、for
ループに入る前に max_value
に何らかの値を代入しておく必要があります。
代入を忘れると max_value
に「不定値」が格納された状態で比較が行われてしまうので、不定値の値によっては上手く最大値が求められなくなってしまいます。
配列の中の最大値以下の値を代入しておく必要あり
具体的に、max_value
に代入しておく必要のある値は「配列 nums
の最大値以下の値」となります。
例えば下の図の配列において、max_value = 53
としてから for
ループを実行しても一度も max_value
が更新されず、配列内に存在しない 53
が最大値 max_value
として返却されてしまいます(逆に max_value
を 52
以下とした場合、正しく最大値が求められることも確認できると思います)。
このようなことにならないように、max_value
には「確実に配列 nums
の最大値以下である」と言える値を代入しておく必要があります。
配列の中の最大値以下の値とは
で、「確実に配列 nums
の最大値以下である」と言える値が、配列 nums
の要素のいずれかとなります。配列 nums
の最大値を超える値が配列 nums
の要素の中にあったらおかしいですよね。
ですので、for
ループに入る前に max_value
に nums
の要素のいずれかを代入しておけば、max_value
は「確実に配列 nums
の最大値以下である」と言える値となり、上手く最大値を求めることができるようになります。
上記の関数では nums[0]
を代入していますが、nums[0]
〜 nums[n - 1]
のどれを代入しても上手く最大値を求めることができます。ただ、配列の先頭 or 末尾の値を代入しておく方が、ソースコードとしては分かりやすいとは思います。
もちろん max_value
には「確実に配列 nums
の最大値以下である」と言える値であれば他の値を代入しておくのでも良いです。
例えば配列内に正の値しか格納されていないことが保証できるのであれば、max_value
に 0
や負の値を代入しておくのでもオーケーです。
ただ、その辺りを考慮するくらいであれば、素直に配列のいずれかの値を代入する方が楽かなぁとは思います。
ちなみに、ここまでの話は「単なる最大値」を求める場合の話であって、下記ページのように「最大値の持つ要素の添字」を求める際には、max_value
に設定する値をもっとしっかり考慮して決める必要があります。
スポンサーリンク
まとめ
このページでは、C言語での「最大値・最小値」の求め方について解説しました!
2つの値から最大値を求める際には、単に2つの値の比較を行い、大きい方を最大値としてやれば良いだけです。また最小値に関しては、最大値を求めるときと比較演算子を逆にしてやることで求めることが出来ます。
配列の中から最大値を求める際にも基本は2つの値の比較の繰り返しを行えば良いだけですが、最大値よりも大きな値を見つけた際に最大値を更新する必要があるので注意してください。
また、繰り返し処理を行う前には仮の最大値の設定を行う必要がある点にも注意してください。仮の最大値としては「配列の要素のいずれかの値」とするのが楽だと思います。
最大値や最小値を求める処理は度々必要になりますので、関数や関数マクロとして用意しておくと便利だと思います!
単に最大値を求めるのではなく、「配列の中の最大値を持つ要素の添字」を求めたくなる事もよくあります。この方法に関しては下記ページで解説していますので、是非こちらのページも続けて読んでみてください!
【C言語】配列の中から最大値を持つ要素の”添字”を求めるオススメの参考書(PR)
C言語学習中だけど分からないことが多くて挫折しそう...という方には、下記の「スッキリわかるC言語入門」がオススメです!
まず学習を進める上で、参考書は2冊持っておくことをオススメします。この理由は下記の2つです。
- 参考書によって、解説の仕方は異なる
- 読み手によって、理解しやすい解説の仕方は異なる
ある人の説明聞いても理解できなかったけど、他の人からちょっと違った観点での説明を聞いて「あー、そういうことね!」って簡単に理解できた経験をお持ちの方も多いのではないでしょうか?
それと同じで、1冊の参考書を読んで理解できない事も、他の参考書とは異なる内容の解説を読むことで理解できる可能性があります。
なので、参考書は2冊持っておいた方が学習時に挫折しにくいというのが私の考えです。
特に上記の「スッキリわかるC言語入門」は、他の参考書とは違った切り口での解説が豊富で、他の参考書で理解できなかった内容に対して違った観点での解説を読むことができ、オススメです。題名の通り「なぜそうなるのか?」がスッキリ理解できるような解説内容にもなっており、C言語入門書としてもかなり分かりやすい参考書だと思います。
もちろんネット等でも色んな観点からの解説を読むことが出来ますので、分からない点は別の人・別の参考書の解説を読んで解決していきましょう!もちろん私のサイトも参考にしていただけると嬉しいです!
入門用のオススメ参考書は下記ページでも紹介していますので、こちらも是非参考にしていただければと思います。
https://daeudaeu.com/c_reference_book/