計算機プログラミング I 第 8 回

30
計計計計計計計計計計I (計計) 2003計計 1 計計計計計計計計計計 I 計8計 •計計計計計計計計計計計計計 •計計計計計計計計計計計計計 –計計計計計計計計計計計計計 –計計計計計計計計計計計計 •計計計計計計

description

計算機プログラミング I 第 8 回. 素数を見つけるアルゴリズム 継承とインスタンスメソッド オブジェクトに機能を加える オブジェクトの機能を変更 クラスの設計. 単純な方法 : i が素数かどうか 2 ~ (n-1) で割ってみる→約 i 回の計算 i が 2 から n まで調べる→ 2+3+…+n= 約 n 2 回の計算 エラトステネスのふるい i 番目が素数→ n/i 回の計算 i=2 から n-1 まで全て素数だったとして n/2 + n/3+…+n/(n-1) < an log(n) 回の計算 ( 素数の存在確率を無視 ) - PowerPoint PPT Presentation

Transcript of 計算機プログラミング I 第 8 回

Page 1: 計算機プログラミング I 第 8 回

計算機プログラミングI (増原) 2003年度

1

計算機プログラミング I第 8 回

•素数を見つけるアルゴリズム•継承とインスタンスメソッド

–オブジェクトに機能を加える–オブジェクトの機能を変更

•クラスの設計

Page 2: 計算機プログラミング I 第 8 回

計算機プログラミングI (増原) 2003年度

2

2 から n が素数かどうかを判定するのに必要な計算回数

• 単純な方法 : –i が素数かどうか 2 ~ (n-1)

で割ってみる→約 i 回の計算–i が 2 から n まで調べる→ 2

+3+…+n= 約 n2 回の計算• エラトステネスのふるい

–i 番目が素数→ n/i 回の計算–i=2 から n-1 まで全て素数

だったとして n/2 + n/3+…+n/(n-1) < an log(n) 回の計算

( 素数の存在確率を無視 )–ただし大きさ n の配列が必

• フェルマーのテスト ( 単純 )– 1 回のテストは ai の計算→ i 回

の掛け算– i が 2 から n まで各 b 回テスト→

約 bn2 回の計算• フェルマーのテスト ( 工夫 )

– ai の計算=ai/2 の計算 +1 回=(ai/4 の計算 +1 回 )+1 回 =…=a0 の計算 +1 回 + ・・・ +1 回= 約 log(i) 回

– i が 2 から n まで各 b 回テスト合計 bn log(n) 回以下の計算

– 確率的

Page 3: 計算機プログラミング I 第 8 回

計算機プログラミングI (増原) 2003年度

3

計算量2 から n が素数かどうか• 単純な方法 : 約 n2 回• エラトステネスのふるい

–約 n log(n) 回–大きさ n の配列が必要

• フェルマーのテスト ( 単純 ):約 bn2 回

• フェルマーのテスト ( 工夫 ):約 bn log(n) 回

• 定数を無視して考えたものを「計算量」という– O(n2), O(n log(n)) のよ

うに書く– おおまかな計算時間

( とメモリの量 ) を比べるため

– 例 : 非常に大きな素数を見つけたい場合

Page 4: 計算機プログラミング I 第 8 回

計算機プログラミングI (増原) 2003年度

4

n2 回と n log(n) 回の違い

01E+152E+153E+154E+155E+156E+157E+158E+159E+15

0 2E+07 4E+07 6E+07 8E+07 1E+08

n*nn log(n)

Page 5: 計算機プログラミング I 第 8 回

計算機プログラミングI (増原) 2003年度

5

最大のメルセンヌ素数分散コンピューティングで栄誉

ある大発見を (ZDNN 2001/12/17)…… コンピュータを使って,こ

れまでに発見された中で世界最大の素数を発見した。……メルセンヌ素数と呼ばれる特殊なタイプの素数を発見するプロジェクトに参加……発見した素数は, 2 の 1346万 6917 乗マイナス 1 ,桁数は 405万 3946 桁にもなる。

メルセンヌ素数は,「 2 の p 乗マイナス 1 ( p は普通の素数)」という特殊なタイプの素数を研究していたフランスの修道士, Marin Mersenne ( 1588 ~ 1648 )にちなんで名付けられた。

メルセンヌ素数は普通の素数よりもはるかに珍しい。これまでのところ, 39 のメルセンヌ素数が発見されている……発見した数値がメルセンヌ素数であることを確認するのに 42 日間かかった。その後研究者がワークステーション 1 台を使って, 3 週間かけて確認作業を行った。http://www.zdnet.co.jp/news/0112/17/e_distributed.html

40 番目のメルセンヌ素数の発見 ! (2003/12/3)

値は 220,996,011-1

桁数は 6,320,430 桁http://www.mersenne.org/

Page 6: 計算機プログラミング I 第 8 回

計算機プログラミングI (増原) 2003年度

6

継承とインスタンスメソッド• オブジェクトに機能を加えたい !

だけど、いままでのプログラムは変えたくない !だからといってプログラムのコピーもしたくない !

継承を使って新しいクラスを作る新しいインスタンス変数を追加する新しいインスタンスメソッドを追加する

• オブジェクトの機能を変更したい ! だけど ( 以下略 ) 継承を使って新しいクラスを作る

すでにあるインスタンスメソッドを再定義する

Page 7: 計算機プログラミング I 第 8 回

計算機プログラミングI (増原) 2003年度

7

例題 : タートルで n 角形を描く• いままでの Turtle オブジェクトができること

–前進 (fd) ・回転 (lt) 等の指示を受ける• Turtle オブジェクトに「長さ l の n 角形を描け」という指示が出せたなら・・・

Turtle m = new Turtle();m.polygon(100,5); // 1 辺 100 の 5 角形

• でも…–Turtle クラスは変更したくない–Turtle.java のコピーを作るのは面倒

Page 8: 計算機プログラミング I 第 8 回

計算機プログラミングI (増原) 2003年度

8

例題 : タートルで n 角形を描く• Turtle クラスを拡張して、 House クラスを定義する• House クラスにインスタンスメソッドを追加する

–「 n 角形を描く」 polygon

–「家の形を描く」 house

House オブジェクトに対しては、 fd, lt 等の他に追加された polygon, house メソッドも呼び出せる

※ House オブジェクトを使っていないプログラムには影響がない !

Page 9: 計算機プログラミング I 第 8 回

計算機プログラミングI (増原) 2003年度

9

n 角形の描き方を知っているタートルがいたら・・・

House ・・・Turtle のかわりのク

ラス名

House ・・・Turtle のかわりのク

ラス名

Turtle オブジェクトと

同じように使える

Turtle オブジェクトと

同じように使える

Turtle にはないメソッドもあるTurtle にはないメソッドもある

public class T61 { public static void main(String[] args){ TurtleFrame f = new TurtleFrame( ); House m = new House( ); int s = 50; f.add(m); m.house(s); m.up( ); m.fd(s * 2); m.down( ); m.polygon(3, s / 2); m.up( ); m.fd(s); m.down( ); m.polygon(10, s / 5); }}

Page 10: 計算機プログラミング I 第 8 回

計算機プログラミングI (増原) 2003年度

10

n 角形の描き方を知っているタートルの定義

Turtle に機能を追加したクラスを作ると宣言Turtle に機能を追加したクラスを作ると宣言

追加される機能( メソッド )

追加される機能( メソッド )

自分自身を使ってn 角形を描く

自分自身を使ってn 角形を描く

自分自身を使って家の形を描く

自分自身を使って家の形を描く

public class House extends Turtle { public void polygon(int n, int s){ int a = 360/n; for(int j = 0; j < n; j++){ fd(s); rt(a); } } public void house(int s){ polygon(4,s); fd(s); rt(30); polygon(3,s); lt(30); bk(s); }}

Page 11: 計算機プログラミング I 第 8 回

計算機プログラミングI (増原) 2003年度

11

n 角形の描き方を知っているタートルの定義

自分自身 (=m) に対するメソッドの実行→m.fd(s) と同じ

→ m が前進

自分自身 (=m) に対するメソッドの実行→m.fd(s) と同じ

→ m が前進

例 :m.polygon(50,3) を実行

→m に対して「多角形を描け」

→ このメソッドが実行

例 :m.polygon(50,3) を実行

→m に対して「多角形を描け」

→ このメソッドが実行

自分自身 (=m) に対するメソッドの実行

追加したメソッドも実行可

自分自身 (=m) に対するメソッドの実行

追加したメソッドも実行可

public class House extends Turtle { public void polygon(int n, int s){ int a = 360/n; for(int j = 0; j < n; j++){ fd(s); rt(a); } } public void house(int s){ polygon(4,s); fd(s); rt(30); polygon(3,s); lt(30); bk(s); }}

文法 : “static” が無い以外はクラスメソッドと

同じ

文法 : “static” が無い以外はクラスメソッドと

同じ

Page 12: 計算機プログラミング I 第 8 回

計算機プログラミングI (増原) 2003年度

12

例題 2: n 角形を分割して描く亀• 「長さ l の n 角形を分割して描く」 Turtle

–「 1 ステップ進め」と言われると、 n 角形の 1 辺だけを描く

–「 1 ステップ進め」というときに、いちいち 1 辺の長さや何角形であるかを指示したくない 次に「進め」と言われたら

• まだ進むべきか ?• 何度曲がるか ?• 何歩進むか ?

次に「進め」と言われたら• まだ進むべきか ?• 何度曲がるか ?• 何歩進むか ?

Stepper m = 長さ 50 の 5 角形を描く亀 ;Stepper m1 = 長さ 30 の 8角形を描く亀 ;m.step(); //5 角形の 1 辺を描くm1.step(); //8角形の 1 辺を描く・・・

Page 13: 計算機プログラミング I 第 8 回

計算機プログラミングI (増原) 2003年度

13

例題 2: n 角形を分割して描く亀• 各 Turtle が「 1 辺の長さがいくつの」「何角形」を

「何番目の辺」まで描いたかを覚える必要がある → インスタンス変数

• Turtle を拡張して Stepper クラスを作る– インスタンス変数を定義する

• 1 辺の長さ• 何角形か• 何番目の辺まで描いたか

– 「 1 ステップ進め」インスタンスメソッドを定義• 全ての辺を描き終えたか ? まだだったら• 前進・回転して• 「何番目の辺まで描いたか」を 1 増やす

オブジェクトに状態を持たせる

Page 14: 計算機プログラミング I 第 8 回

計算機プログラミングI (増原) 2003年度

14

6.4 インスタンス変数自分がいま• 何角形を描いているのか • 1辺の長さ• 何番目の辺を描いているのかを覚える

• ローカル変数と同様に• 値をとり出す• 値をしまう

ことができる

• オブジェクトごとに用意される→ 前回のメソッド実行時に

しまわれた値がそのまま残っている

j=j+1;if(j==n) ...と同じ

インスタンス変数の宣言

インスタンス変数の宣言public class Stepper extends Turtle{

public int n; public int size; private int j = 0; public static final int ALREADY_FIN = 0; public static final int JUST_FIN = 1; public static final int NOT_FIN = 2; public int step() { if(j >= n) return ALREADY_FIN; fd(size); rt(360/n); if(++j == n) return JUST_FIN; return NOT_FIN; } public void reset() { j = 0; }}

Page 15: 計算機プログラミング I 第 8 回

計算機プログラミングI (増原) 2003年度

15

6.4 インスタンス変数自分がいま• 何角形を描いているのか • 1辺の長さ• 何番目の辺を描いているのかを覚える

• ローカル変数と同様に• 値をとり出す• 値をしまう

ことができる

• オブジェクトごとに用意される→ 前回のメソッド実行時に

しまわれた値がそのまま残っている

j=j+1;if(j==n) ...と同じ

public class Stepper extends Turtle{ public int n; public int size; private int j = 0; public static final int ALREADY_FIN = 0; public static final int JUST_FIN = 1; public static final int NOT_FIN = 2; public int step() { if(j >= n) return ALREADY_FIN; fd(size); rt(360/n); if(++j == n) return JUST_FIN; return NOT_FIN; } public void reset() { j = 0; }}

public class T62{ public static void main(String[] args){ TurtleFrame f = new TurtleFrame(); Stepper m1 = new Stepper(); f.add(m1); Stepper m2 = new Stepper(); f.add(m2); m1.n = 4; m1.size = 100; m2.n = 3; m2.size = 100; ...

public class T62{ public static void main(String[] args){ TurtleFrame f = new TurtleFrame(); Stepper m1 = new Stepper(); f.add(m1); Stepper m2 = new Stepper(); f.add(m2); m1.n = 4; m1.size = 100; m2.n = 3; m2.size = 100; ...

j=j+1;(++j == n)

Page 16: 計算機プログラミング I 第 8 回

計算機プログラミングI (増原) 2003年度

16

6.5 コンストラクタ• インスタンス変数 = オブジェクトごとにある状態• オブジェクトを作る (new) と、初期化をする ( 例 : インスタンス変数に適当な値をしまう ) これを一体化したい ! コンストラクタ

• オブジェクトが作られたときに実行されるメソッド• 文法 : クラス名 (引数の型 引数の名前 , ...) { 文 ; ... }

( メソッド定義に似ている。違うのは返り値の型が無い点と名前 )

• 継承とコンストラクタ–子クラスのコンストラクタから親クラスのコンストラクタを呼び出す

super(引数 , 引数 , ...);–子クラスのコンストラクタは、一番初めにこれをしなければいけない–省略すると「引数の無いコンストラクタ」が自動的に呼び出される– しかし親クラスが「引数の無いコンストラクタ」を定義していないとエラー

Page 17: 計算機プログラミング I 第 8 回

計算機プログラミングI (増原) 2003年度

17

public class Stepper extends Turtle{ public int n; public int size; private int j = 0;

Stepper(int x, int y, int angle, int n, int size) { super(x, y, angle); this.n = n; this.size = size; }... public int step() { if(j >= n) return ALREADY_FIN; ...

Stepper(int x, int y, int angle, int n, int size) { super(x, y, angle); this.n = n; this.size = size; }

コンストラクタの定義

コンストラクタの定義

super(x, y, angle);親クラスの

コンストラクタを実行... new Turtle(x,y,angle)

のときと同様

親クラスのコンストラクタを実行

... new Turtle(x,y,angle)のときと同様

Stepper

Stepper

コンストラクタの実例

Stepper[] hm = new Stepper[10]; for(int i = 0 ; i < 10; i++){

hm[i] = new Stepper(i * 50 + 25,150,0, n[i], size[i]); hm[i].setColor(c[i % c.length]); f.add(hm[i]); }

new Stepper(i * 50 + 25,150,0, n[i], size[i]);

1. Stepper オブジェクトが作られる2. コンストラクタが実行される1. Stepper オブジェクトが作られる2. コンストラクタが実行される

Page 18: 計算機プログラミング I 第 8 回

計算機プログラミングI (増原) 2003年度

18

例題 3: 点線を描く亀

• Turtle オブジェクトが fd したときに点線を描かせたい ! でも Turtle クラスは変更したくない !

継承とインスタンスメソッドの再定義• 例 :

Tensen House

polygon(5,50) polygon(5,50)

違い : fd メソッドを点線を描きながら進むように

再定義している

Page 19: 計算機プログラミング I 第 8 回

計算機プログラミングI (増原) 2003年度

19

例題 3: 点線を描く亀

点線を描く亀を作るには• House クラスの子クラス Tensen クラスを定義する• Tensen クラスに fd メソッドを定義する―― 再定義

という• そのメソッド中でペンを上げ下げしながら n 進む

Tensen House

polygon(5,50) polygon(5,50)

Page 20: 計算機プログラミング I 第 8 回

計算機プログラミングI (増原) 2003年度

20

点線で多角形を描くpublic class Tensen extends House{ int psize = 4; (略 : コンストラクタ ) public void fd(int s){ 長さ s の点線を描く }

public static void main(String[] args){ (略 : TurtleFrame の生成 ) Tensen m = new Tensen(); (略 ) m.polygon(5, 50); }}

1. main から実行が始まる2. Tensen オブジェクトが

作られる

3. Tensen オブジェクトの ploygon メソッドを呼び出す

4. ploygon メソッドはn 角形を描く。その際、 Tensen オブジェクトのfd は点線を描くように再定義されているので、n 角形は点線で描かれる。

Page 21: 計算機プログラミング I 第 8 回

計算機プログラミングI (増原) 2003年度

21

点線で多角形を描くpublic class Tensen extends House{ int psize = 4; (略 : コンストラクタ ) public void fd(int s){ 長さ s の点線を描く }

public static void main(…){ (略 : TurtleFrame の生成 ) Tensen m = new Tensen(); (略 ) m.polygon(5, 50); }}

public class House extends Turtle { public void polygon(int n, int s){ int a = 360/n; for(int j = 0; j < n; j++){ fd(s); rt(a); } }}

ここからスタート

オブジェクトを作る

メソッド呼び出し

polygon

親クラスから継承した polygon を

実行

自身の fd を呼び出し

fd

再定義されたfd が実行

Tensen

Page 22: 計算機プログラミング I 第 8 回

計算機プログラミングI (増原) 2003年度

22

点線で多角形を描くpublic class Tensen extends House{ int psize = 4; (略 : コンストラクタ ) public void fd(int s){ 長さ s の点線を描く }

public static void main(…){ (略 : TurtleFrame の生成 ) Tensen m = new Tensen(); (略 ) m.polygon(5, 50); }}

public class House extends Turtle { public void polygon(int n, int s){ int a = 360/n; for(int j = 0; j < n; j++){ fd(s); rt(a); } }}

再定義されたfd が実行

結果 : 点線で 5 角形が描かれる

Tensen

Page 23: 計算機プログラミング I 第 8 回

計算機プログラミングI (増原) 2003年度

23

extends

点線で多角形を描くしくみ

Tensen

extends

Turtle クラスfd(s):実線を描きながら前進

rt(a):右回転

House クラスfd(s):継承(実線を描きながら前進 )

polygon(n,s):fd を使って多角形を描く

Tensen クラスfd(s):点線を描きながら前進

polygon(n,s):継承(fd を使って多角形を描く )

所属

• Tensen オブジェクトへの polygon メソッドの呼び出しは、親クラスの継承された定義の実行になる

• polygon メソッド中での fd メソッドの呼び出しは、 Tensenオブジェクトへのメソッド呼び出しなので、再定義された fd が実行される

Page 24: 計算機プログラミング I 第 8 回

計算機プログラミングI (増原) 2003年度

24

親クラスのメソッドを使う方法• メソッドを再定義すると、

親クラスのメソッド定義が使えなくなる例 : Tensen オブジェクトの fd メソッド

• メソッド中でsuper . メソッド名 (引数 , ...)

のようにメソッドを呼び出すと、親クラスのメソッドを実行できる

例 : Tensen オブジェクトの fd メソッド中でsuper.fd(psize)

とすると、 Turtle クラスに定義された本来の fd メソッドが実行される

Page 25: 計算機プログラミング I 第 8 回

計算機プログラミングI (増原) 2003年度

25

点線を描くしくみpublic class Tensen extends House{ int psize = 4; (略 : コンストラクタ ) public void fd(int s){ 長さ s の点線を描く }

public static void main(…){ (略 : TurtleFrame の生成 ) Tensen m = new Tensen(); (略 ) m.polygon(5, 50); }}

public class House extends Turtle { public void polygon(int n, int s){ int a = 360/n; for(int j = 0; j < n; j++){ fd(s); rt(a); } }}

?

Page 26: 計算機プログラミング I 第 8 回

計算機プログラミングI (増原) 2003年度

26

点線を描くしくみpublic class Tensen extends House{ int psize = 4; (略 : コンストラクタ ) public void fd(int s){ 長さ s の点線を描く }

public static void main(…){ (略 : TurtleFrame の生成 ) Tensen m = new Tensen(); (略 ) m.polygon(5, 50); }}

public class House extends Turtle { public void polygon(int n, int s){ int a = 360/n; for(int j = 0; j < n; j++){ fd(s); rt(a); } }}

public void fd(int s){ int k, len; for(k = 0, len = 0 ; len + psize <= s; k++, len+= psize){ if(k % 2 == 0) down(); else up(); super.fd(psize); } down(); super.fd(s - len); }

public void fd(int s){ int k, len; for(k = 0, len = 0 ; len + psize <= s; k++, len+= psize){ if(k % 2 == 0) down(); else up(); super.fd(psize); } down(); super.fd(s - len); }

ペンを交互に上げ下ろししながら、psizeづつ前進する

super . メソッド名 ( 引数式 , …) 親クラスのメソッドを呼び出す

Page 27: 計算機プログラミング I 第 8 回

計算機プログラミングI (増原) 2003年度

27

extends

点線を描くしくみ

Tensen

extends

Turtle クラスfd(s):実線を描きながら前進

rt(a):右回転

House クラスfd(s):継承(実線を描きながら前進 )

polygon(n,s):fd を使って多角形を描く

Tensen クラスfd(s):ペンを上下させながらsuper.fd(psize) を呼び出し

polygon(n,s):継承(fd を使って多角形を描く )

所属

• Tensen オブジェクトの fd メソッドを呼び出すと、再定義されたメソッドが実行される

•再定義されたメソッド中の super.fd(psize) は親クラスの fd メソッドを実行する。結果、 Turtle クラスの fd メソッドが実行され、実線が描かれる

Page 28: 計算機プログラミング I 第 8 回

計算機プログラミングI (増原) 2003年度

28

extends

まとめると・・・

Tensen

extends

Turtle クラスfd(s):実線を描きながら前進

rt(a):右回転

House クラスfd(s):継承(実線を描きながら前進 )

polygon(n,s):fd を使って多角形を描く

Tensen クラスfd(s):ペンを上下させながらsuper.fd(psize) を呼び出し

polygon(n,s):継承(fd を使って多角形を描く )

所属

polygon

fd

Page 29: 計算機プログラミング I 第 8 回

計算機プログラミングI (増原) 2003年度

29

クラスの拡張class House extends Turtle { … } のようなとき• House は 子クラス または サブクラス• Turtle は 親クラス または スーパークラス• House オブジェクトは、 Turtle オブジェクトが持って

いる全てのメソッドを持つ ( 例 : fd)• House オブジェクトは、 Turtle オブジェクトのかわり

に使える ( 例 : TurtleFrame オブジェクトに add できる )Turtle m = new House(); ということが可能 !

• House オブジェクトは Turtle オブジェクトと違った動きをするかも知れない ( 例 : fd の再定義 )

Page 30: 計算機プログラミング I 第 8 回

計算機プログラミングI (増原) 2003年度

30

クラスの設計―― Turtle クラスの解剖

public class Turtle{ public Color kameColor = Color.green; TurtlePanel f; // 表示面画 double angle; // 角度 double x, y; // 位置 double dx, dy; // sin(a),-cos(a) boolean penDown; // ペン状態 Color c = Color.black; // ペンの色

// コンストラクタ public Turtle(int x,int y, int ia) { this.x = ((double)x + 0.5); this.y = ((double)y + 0.5); setangle((double)ia *Math.PI/180.0); penDown = true; }

// インスタンスメソッド public void fd(int n) {

double xx = x; double yy = y; x = xx + dx * n; y = xx + dy * n; if (penDown) { f.addLineElement((int)xx, (int)yy,

(int)x, (int)y, c); } kameShow(moveWait); } …}