c言語の課題を(エクストリームに)解こう #1

25
C言語の課題を (エクストリームに)解こう techno@Hirotaka Kawata 筑波大学 情報学群 情報科学類 1年

Upload: university-of-tsukuba-linux-user-group

Post on 24-May-2015

1.056 views

Category:

Education


2 download

DESCRIPTION

筑波大学 Linux User Group (つくらぐ)http://www.tsukuba-linux.org/

TRANSCRIPT

Page 1: C言語の課題を(エクストリームに)解こう #1

C言語の課題を

(エクストリームに)解こう

techno@Hirotaka Kawata筑波大学 情報学群 情報科学類 1年

Page 2: C言語の課題を(エクストリームに)解こう #1

プログラミング入門1の課題

ここからみれます。今回は、課題2 をやります。

http://www.ialab.is.tsukuba.ac.jp/~maeda/class/prog1/  多分、みなさんなら、きっと簡単な課題でしょう!僕には、むずかしすぎて...(笑

ちょっと、情報科学類1年生の内輪向けですが...

 

Page 3: C言語の課題を(エクストリームに)解こう #1

ここでやること。

プログラミング入門 1 の課題を、究極の形で、皆さんと一緒に解いてきましょう。

 条件:

課題の本来の趣旨を守る無理しすぎないなるべく効率の良いコードを(?)

Page 4: C言語の課題を(エクストリームに)解こう #1

やってみよう。

そうしよう。

Page 5: C言語の課題を(エクストリームに)解こう #1

課題1

整数を入力し,入力された値が偶数か奇数かを判定して出力するプログラムを作成しなさい.

よくありそうな、課題ですねー。きっと頭にうかんだ演算子は...

Page 6: C言語の課題を(エクストリームに)解こう #1

 ですよね....

Page 7: C言語の課題を(エクストリームに)解こう #1

念のため、聞いておきます。

多分いちばん代表的なやり方は

 if(i % 2) { 奇数 }

else { 偶数 }

 % (あまりを求める演算子) 以外を使おうとした人。いてほしい...

Page 8: C言語の課題を(エクストリームに)解こう #1

もし % が使えなかったら...

どうするおつもりですか?

 偶数であるか奇数であるかを見分ける方法...思いつきますか?

決して、ずっと / (割り算) していくなんてことはしませんよ。

Page 9: C言語の課題を(エクストリームに)解こう #1

例えばこんな例も...

0000 0001 -> 11111 1111 -> -1 (2の補数表現)

0000 0010 -> 21111 1110 -> -2 (2の補数表現)

0000 0011 -> 31111 1101 -> -3

なんだか気付きませんか?

Page 10: C言語の課題を(エクストリームに)解こう #1

デジタル人間なら、

2進数で考えよう。

 偶数だと、必ず最下位ビットが 0 になる。奇数だと、必ず最下位ビットが 1 になる。

 という法則がある。これを利用しよう。

Page 11: C言語の課題を(エクストリームに)解こう #1

マスクしましょう。

たとえば、5 が偶数か奇数か調べたいとき。

0000 0101 == 5

00000101 & 00000001= 00000001

if(i & 0x01) {} じゃだめですか?

Page 12: C言語の課題を(エクストリームに)解こう #1

実際どっちがいいのよ...

んー。

% を、CPU がどんな計算してるんだかわからん。(知識不足)たぶん、そんな命令もなかったはずだし。

マスクしたほうが、オールマイティーに早い。とおもう。(どんなCPUでもってこと)だけど、コード読みづらくなるかも...コメント重要。

Page 13: C言語の課題を(エクストリームに)解こう #1

課題 2

100点満点の点数を入力し、 50点以上であれば、A、50点未満であれば、B、0から100の数字でなければ、errorと出力するプログラムを作成しなさい.

おー。これもなかなかおもしろそう。

Page 14: C言語の課題を(エクストリームに)解こう #1

一般的なやり方

if(a < 0 && a > 100) {    if(a >= 50) { puts("A"); }    else           { puts("B"); }}else { puts("error"); }

こんな感じだと思うのですがいかがでしょう?やり方は、いっぱいありますが。

Page 15: C言語の課題を(エクストリームに)解こう #1

だけど...

先程の例は、問題の文章通りに設計書を書いただけ。

 ここから、人力最適化のお時間です。コンパイラの最適化なんかあてにしちゃーいけません。そもそも、コンパイラの最適化は、設計書に書いてあることに忠実に、ちまちまやってるだけだし。

Page 16: C言語の課題を(エクストリームに)解こう #1

人力最適化。

if(a >= 0 && a <= 100) {    if(a >= 50) { puts("A"); }    else           { puts("B"); }}else { puts("error"); } error は最大 2 回の比較。

A, B は 3 回の比較。

という感じになります。

Page 17: C言語の課題を(エクストリームに)解こう #1

人力最適化。

たとえば、違う実装。

if(i >= 50 && i <= 100)   { puts("A"); }else if(i < 50 && i >= 0) { puts("B"); }else                             { puts("error"); }

error は 3 回の比較。

A, B は最大 3 回の比較。 コードを短くすればいいというものではない。

Page 18: C言語の課題を(エクストリームに)解こう #1

人力最適化

if(i >= 50) {  if(i <= 100) { puts("A"); }  else { puts("error"); }}else {  if(i >= 0) { puts("B"); }  else { puts("error"); }}

error は 2 回の比較

A, B も 2 回の比較

完璧じゃない?ご想像にお任せします。

Page 19: C言語の課題を(エクストリームに)解こう #1

ただ、よくみると....

なんだか、行数が多い?

 そう、コード量が若干多くなりました。

error を 2 回出力させているんです。

 ということは、バイナリのサイズもでかくなる。(goto でジャンプさせるってのもありだけど、たぶん else で JMP したあとに、

goto でもう一度 JMP するような気もするので、実行時間的には JMP 命令だからといえど、最適なコードとは言えない...)(そうだ、アセンブラだ!!!)

Page 20: C言語の課題を(エクストリームに)解こう #1

人力最適化はほどほどに。

もうちょっと、語ると...

なんだか、あとのコードになるほど、理解しづらくなったとは思いませんか?

 変に最適化しすぎると、コードが読みづらくなって、コードも長くなって... という状況になることが。まあ、ほどほどに。

Page 21: C言語の課題を(エクストリームに)解こう #1

課題 3

二つの整数値A、Bを読み込んで,BがAの約数かどうかを判定する プログラムを作りなさい.表示は以下のようにしなさい.

 つまんねーな。これが一番単純じゃん?

Page 22: C言語の課題を(エクストリームに)解こう #1

いきなりだけど、解答例。

if(a % b) {  puts("n");}else {  puts("y");} これ以上、どうしろっていうの...ちょっと思いつきませんでした。

Page 23: C言語の課題を(エクストリームに)解こう #1

課題3について議論?

なんかありますかね?

Page 24: C言語の課題を(エクストリームに)解こう #1

最後に...

普通に解いて終わりでは、つまらない!とおもった、techno のお遊びでした。

これからも、また不定期にやるかもしれません。(LT とかで)プログラミングの面白さが少しでも分かってくれたら...

1年生いっぱいよんできてください。以上。

Page 25: C言語の課題を(エクストリームに)解こう #1

ご清聴ありがとうございました。