C言語の中央値を求めるアルゴリズムについて

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ブルース
記事: 10
登録日時: 10年前

C言語の中央値を求めるアルゴリズムについて

#1

投稿記事 by ブルース » 10年前

C言語のアルゴリズムの参考書を読んで今勉強してるんですが。
中央値を求めるアルゴリズムについて頭を悩ませています。
三個の数字を比較して中央値を求めるif文なんですが

コード:

#include <stdio.h>
int med3(int a, int b, int c)
{
      if (a >= b)
         if (b >= c)
             return b;
         else if (a <= c)
             return a;
         else
             return c;
      else if (a > c)
             return a;
      else if (b > c)
              return c;
      else
              return b;
}

int main(void)
{
         int a, b, c;

         printf("三つの整数の中央値を求めます /n");
         printf("aの値:");     scanf("%d", &a);
         printf("bの値:");     scanf("%d", &b);
         printf("cの値:");     scanf("%d", &c);

        printf("中央値は%dです。 /n", med3(a, b, c));

        return 0;
}
この大量のifのネストがいまいち分かりません。参考書にも解説は載っていないし、ググっても出てこないし
途方に困っています。私自身内容自体はなんとなくわかるんですがどうしてこういう式になったのかが解説がないのです。是非ご教授いただけたらありがたいです。

初級者
記事: 200
登録日時: 13年前

Re: C言語の中央値を求めるアルゴリズムについて

#2

投稿記事 by 初級者 » 10年前

何か適当な数値を決めた後、
自分がコンピューターに
なったつもりで、ロジックを
追ってみましょう。

ちなみに、
誤:途方に困る
正:途方に暮れる

ブルース
記事: 10
登録日時: 10年前

Re: C言語の中央値を求めるアルゴリズムについて

#3

投稿記事 by ブルース » 10年前

コンピュータになったつもりでってなれたら楽なんですけどね
この式の考え方が分からないと言いますか。おそらく全通りを順番通りに比較して二番目の値を出しているんでしょうが。最初はAの値とB、Cと比較して、次はB次はCって感じはなんとなくは掴めましたが順番を変えて式を作れとか、論理和とか&&を使って出せと言われると急にわけがわからなくなります。
多分根本的な事を理解していないんだと思います。

初級者
記事: 200
登録日時: 13年前

Re: C言語の中央値を求めるアルゴリズムについて

#4

投稿記事 by 初級者 » 10年前

3個の数値を、例えば 10, 20, 30
とすると、変数 a, b, c に当てはめる
場合の数 = 3! = 6とおりです。
そのすべてについて、
自分がコンピューターになったつもりで
ロジックを追いかけてみる、
というのはむずかしいことですか?

初級者
記事: 200
登録日時: 13年前

Re: C言語の中央値を求めるアルゴリズムについて

#5

投稿記事 by 初級者 » 10年前

a ≧ b
のとき、数直線上ではbがaの左側に来る。
3つめの数cが、
bよりも小さければ、中央値はb
aとbの間にあれば、中央値はc
aよりも大きければ、中央値はa

a < b
のときも同様の考え方。aとbの左右が異なるだけ。

さて、これをC言語のコードで書くと、どうなるでしょう。

かずま

Re: C言語の中央値を求めるアルゴリズムについて

#6

投稿記事 by かずま » 10年前

ブルース さんが書きました:この大量のifのネストがいまいち分かりません。
比較演算子が >=, <=, > とバラバラなのも分かりにくい原因かな?
次のように書けばどうでしょうか?

コード:

int med3(int a, int b, int c)
{
    if (a < b)
        if (b < c)       // a < b < c
            return b;
        else if (a < c)  // a < c <= b
            return c;
        else             // c <= a < b
            return a;
    else
        if (a < c)       // b <= a < c
            return a;
        else if (b < c)  // b < c <= a
            return c;
        else             // c <= b < a
            return b;
}

かずま

Re: C言語の中央値を求めるアルゴリズムについて

#7

投稿記事 by かずま » 10年前

かずま さんが書きました:

コード:

        else             // c <= b < a
訂正します。

コード:

        else             // c <= b <= a

ブルース
記事: 10
登録日時: 10年前

Re: C言語の中央値を求めるアルゴリズムについて

#8

投稿記事 by ブルース » 10年前

考え過ぎですかね??まったくわけがわからなくなってきた。
簡単な方の最大値と最小値の代入は理解できたのだけんですけどね
まったく自分の理解力のなさが嫌になります。

初級者
記事: 200
登録日時: 13年前

Re: C言語の中央値を求めるアルゴリズムについて

#9

投稿記事 by 初級者 » 10年前

ものすご~く素直に書いたコードだと思います。

コード:

#include <stdio.h>

int med3(int a, int b, int c)
{
   if (a >= b) {   // 数直線上の位置関係は、-------b-------a-------
       // cがb~aの左側にあれば、bが中央値  ---c---b-------a-------
       // cがb~aの右側にあれば、aが中央値  -------b-------a---c---
       // どちらでもなければ、cが中央値     -------b--c----a-------
       return (c < b) ? b : (c > a) ? a : c;
   }
   else {          // 数直線上の位置関係は、-------a-------b-------
       // cがa~bの左側にあれば、aが中央値  ---c---a-------b-------
       // cがa~bの右側にあれば、bが中央値  -------a-------b---c---
       // どちらでもなければ、cが中央値     -------a--c----b-------
       return (c < a) ? a : (c > b) ? b : c;
   }
}

int main(void)
{
   printf("%d\n", med3(10, 20, 30));
   printf("%d\n", med3(10, 30, 20));
   printf("%d\n", med3(20, 10, 30));
   printf("%d\n", med3(20, 30, 10));
   printf("%d\n", med3(30, 10, 20));
   printf("%d\n", med3(30, 20, 10));
   return 0;
}

林_林檎

Re: C言語の中央値を求めるアルゴリズムについて

#10

投稿記事 by 林_林檎 » 10年前

a, b, c の3つの数字の大きさの関係について質問をして、
3つの数字を順番に並べるクイズを考えてみるます。



a は b 以上ですか? と聞いたとき、“はい”と答えられたら、
  a ≧ b であるということがわかります。

  次に、 b は c 以上ですか? と聞いたとき、“はい”と答えられたら、
    a ≧ b で b ≧ c であるということがわかります。中央値は b です。

コード:

if( a >= b )
  if( b >= c )
    return b;

a は b 以上ですか? と聞いたとき、“はい”と答えられ、
  次に、 b は c 以上ですか? と聞いたとき、“はい”と答えられなければ、
    a ≧ b で c > b であるということがわかります。

    その次に、 a は c 以下ですか? と聞いたとき、“はい”と答えられたら、
      a ≧ b で c > b で c ≧ a であるということがわかります。

      a ≧ b で c > b で c ≧ a ということは、
      c ≧ a で a ≧ b ということです。中央値は a です。

コード:

if( a >= b )
  if( b >= c ) ;
  else if( a <= c )
    return a;

a は b 以上ですか? と聞いたとき、“はい”と答えられ、
  次に、 b は c 以上ですか? と聞いたとき、“はい”と答えられなければ、
  a ≧ b で c > b であるということがわかります。

    その次に、 a は c 以下ですか? と聞いたとき、“はい”と答えられなければ、
      a ≧ b で c > b で a > c であるということがわかります。

      a ≧ b で c > b で a > c ということは、
      a > c で c > b ということです。中央値は c です。

コード:

if( a >= b )
  if( b >= c ) ;
  else if( a <= c ) ;
  else return c;

a は b 以上ですか? と聞いたとき、“はい”と答えられなければ、
  b > a であるということがわかります。

  次に、a は c より大きいですか? と聞いたとき、“はい”と答えられたら、
    b > a で a > c であるということがわかります。中央値は a です。

コード:

if( a >= b ) ;
  else if( a > c )
    return a;

a は b 以上ですか? と聞いたとき、“はい”と答えられず、
  次に、a は c より大きいですか? と聞いたとき、“はい”と答えられなければ、
    b > a で c ≧ a であるということがわかります。

    その次に、 b は c より大きいですか? と聞いたとき、“はい”と答えられたら、
      b > a で c ≧ a で b > c であるということがわかります。

      b > a で c ≧ a で b > c ということは、
      b > c で c ≧ a ということです。中央値は c です。

コード:

if( a >= b ) ;
  else if( a > c ) ;
  else if( b > c )
    return c;

a は b 以上ですか? と聞いたとき、“はい”と答えられず、
  次に、a は c より大きいですか? と聞いたとき、“はい”と答えられなければ、
    b > a で c ≧ a であるということがわかります。

    その次に、 b は c より大きいですか? と聞いたとき、“はい”と答えられなければ、
      b > a で c ≧ a で c ≧ b であるということがわかります。

      b > a で c ≧ a で c ≧ b ということは、
      c ≧ b で b > a ということです。中央値は b です。

コード:

if( a >= b ) ;
  else if( a > c ) ;
  else if( b > c ) ;
  else return b;

言葉にするとすごく長いですね。参考になれば嬉しいです:)

初級者
記事: 200
登録日時: 13年前

Re: C言語の中央値を求めるアルゴリズムについて

#11

投稿記事 by 初級者 » 10年前

林_林檎さんの書いたコードには
多くの誤りがあります。
参考にはなりません。

if

else if
の最後に付いている
セミコロンが余計です。

林_林檎

Re: C言語の中央値を求めるアルゴリズムについて

#12

投稿記事 by 林_林檎 » 10年前

ブルースさん、誤りの入ったコードを提示してしまい、申し訳ありませんでした。
初級者さん、ご指摘いただきありがとうございます:)
また一つ知らないことが知れましたX>

ちなみに、Visual Studio 2012 Professional で以下のプログラムを実行すると

コード:

int f(int x, int y)
{
	if( x >= y ) ;
	else return x;

	return -9999;
}

int main()
{
	int a = 1, b =2;

	printf( "f(a,b) : %d\n", f(a, b) );
	printf( "f(b,a) : %d\n", f(b, a) );

	scanf("%d", &a);
	return 0;
}
出力
f(a,b) : 1
f(b,a) : -9999

となるのですが、これは私の環境でのみ有効な記述で、 if( 式 ) ; else 文; というのは通常は動かないコードなのでしょうか?
もしくは、何もしないで else を書く記述が良くないのでしょうか?

if( x >= y )
  x = x; // 何もしない
else
  return x;

の方が良い記述かもしれません。というか、それぞれの場合に分けたコードを書くというのが、そもそもわかりづらい事だったかもしれません。
あ、ブルースさんの質問と関係なくなってきていますねX(

ブルースさん、重ね重ね、混乱を招くようなことを書いてしまい、すみませんでした。どうかご容赦ください。

管理人さん、申し訳ないのですが返信の削除の方法がわからないので、お手数ですが私の上の返信を削除して下さい。よろしくお願いいたします。

ブルース
記事: 10
登録日時: 10年前

Re: C言語の中央値を求めるアルゴリズムについて

#13

投稿記事 by ブルース » 10年前

購入した参考書が難しかったんだと思います。ここの部分がまったく理解できなかったので飛ばして続きを読んでみたら解説が載ってないのが多々あったので、多分、解説書というより実用書って感じの記述が多く見受けられました。それにこのややこしすぎるプログラムはバグの原因にもなりやすらしいので基本組まないということも本には載っていたので、一旦飛ばして次へ行こうと思います。じゃあなんで解説もなしに書いてあったんだと思いますけど・・・

ずっと悩んでいてもラチがあかないですしね、また別に新しい発見があるかもしれませんので
解説はないのは飛ばして次に行こうと思います。皆さん大変迷惑かけました

アバター
usao
記事: 1889
登録日時: 11年前

Re: C言語の中央値を求めるアルゴリズムについて

#14

投稿記事 by usao » 10年前

>ずっと悩んでいてもラチがあかないですしね、また別に新しい発見があるかもしれませんので
>解説はないのは飛ばして次に行こうと思います。皆さん大変迷惑かけました

これは 本件はわからないまま終了 ということですか?
本に解説があるとか無いとかいうのとは別の話として,
「ここで多くの方に答えていただいた内容を読んでもわからない」ということなのでしょうか?
オフトピック
※「こんなこともわからないのか」とかいうスタンスで言っているのではなくて,
せっかく時間を割いて回答してくださっているのに,全くまともに読まずに終了するのであれば
そもそも何故質問されたのでしょう? とか やや失礼ではありませんかね?
という側を言いたいわけですので誤解なきよう.

N.R

Re: C言語の中央値を求めるアルゴリズムについて

#15

投稿記事 by N.R » 10年前

>これは私の環境でのみ有効な記述で、 if( 式 ) ; else 文; というのは通常は動かないコードなのでしょうか?

実行結果に違いがある場合は誤りでしょうが
特にエラーを出すものではないでしょうね。
(こちらも1つ1つ実行して確認はしてませんが)

分からない人にとってはより難しいコードかもしれません

いずれにせよ何を指して誤りと言っているのかはっきりさせないと議題者もどこを参考にしてはいけなかったのかが分からないと思います

アバター
usao
記事: 1889
登録日時: 11年前

Re: C言語の中央値を求めるアルゴリズムについて

#16

投稿記事 by usao » 10年前

最初の質問文に対して答えるならば,

a,b,cの3つの数について大小を比較する必要がある
→とりあえず最初にaとbについて比較してみると…

コード:

if( a>=b )
{//(1) a>=b の場合
}
else
{//(2) a>=bではない,すなわち a<b の場合
}
この比較だけではまだ答えはわからないので,さらに cを絡めた比較を行ってみる
まずは(2)の側は保留して,(1)の側だけを考えてみる

コード:

if( a>=b )
{//(1) a>=b の場合
  if( b>=c )
  {//(1-1) a>=bであって,さらにb>=cな場合
    return b;  //このとき答えはbだとわかる
  }
  else
  {//(1-2) a>=bであって,さらにb>=cではない,すなわちb<cの場合
     //この場合,まだ答えはわからない
  }
}
else
{//(2) a>=bではない,すなわち a<b の場合
  //とりあえず保留
}
…のように,提示されたコードができていく過程を示したらわかりやすかったのかもしれませんね.
(No10でもそういうことをやっているのだけれど,解決済みの箇所は都度重複して書かずに省略して ; で示していたのだけれど
 そのことを明示的に断らなかったのでうまく伝わらなかったのでしょう.)
オフトピック
個人的には,ifの入れ子で困っている人に対して
3項演算子の入れ子で応じるのは より難しいコードを示した だけな気がします.

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: C言語の中央値を求めるアルゴリズムについて

#17

投稿記事 by ISLe » 10年前

質問者さんは、この手順で中央値が求まることの証明が欲しいということなのでしょう。

コードを読むのに非常に邪魔な欲求ですし、関数原型だけが公開されていれば何の疑問も持たずに使うのでしょうけど。

林_林檎

Re: C言語の中央値を求めるアルゴリズムについて

#18

投稿記事 by 林_林檎 » 10年前

もう解決となったのに返信するのは良くないことかもしれませんが、
私が書いた内容についての返信を書かないのは、より良くないことだと思ったので返信させていただきます;)

N.R さん、お返事ありがとうございます。確かに何種類かのソフトと言語ではエラーが出ませんでした。
しかし、{} を使わない入れ子であるからといって、なるべくそのまま書こうとしたのは上手い方法ではなかったですね。

文章に対応するコードを書くより、コードを毎回コピーして、該当箇所を強調しておくとか(これは投稿が長くなってしまいます)、
最初のコードでの何行目の return に対応するか書くとか(これだと記事を上下に往復することになってしまいます)、
色々考えてみたのですが、最適の方法を思いつけませんでした。


usaoさん、まさにその方法が一番上手い説明の方法ですねX)
{} を使うと、その中がどういう場合に実行されるのかということ書きやすいです。
{} がないと、if else の行末にコメントを書くか途中にコメント行を挿入する形になって、書きづらいです。
そして、補足のつもりで書いたコードなら、そうであるからこそ当然、省略したことについて明示すべきでした。


ブルースさんの質問トピックなのに、やたら多く返信を書いてしまいましたが、
初級者さん、N.R さん、usao さん、大変ありがとうございました。


ブルースさん、わかりづらいところを飛ばして、もっと知識がついた頃に見返すというのはいい方法です。
でも思い悩んだこともきっと無駄にはなりません。すごく印象に残るし、それに関連することへの理解も深まったはずです。
近いうちにこれは“なんだ、こんな簡単なことか”と思えるかもしれません。
そうなったとき、新しい悩みの種ができたら、それは  “なんだ、こんな簡単なことか”と思える一歩前  です。そのときはぜひ最後までチャレンジしてみて下さい:)

閉鎖

“C言語何でも質問掲示板” へ戻る