43
44
代表的なプログラミング言語:
FORTRAN
1950年代に開発された
アセンブリ言語が主流だった時代 科学技術計算プログラムに用いられることが(今で も)多い
高性能なコンパイラがあったため
高性能な数値計算ライブラリが豊富なため――行列計算・統計演算など
45
代表的なプログラミング言語: C
1970年代初頭にUNIX OSとそのアプリケーショ
ンの開発のために作られた
ハードウェアを直接操作するようなプログラムを書ける~~ アセンブリ言語に近い
それでいて高級言語 ~~ 色々なCPUで動く 現在でも多くのソフトウェアの開発に利用
安全性の配慮は少ない
脆弱性のあるプログラムを作ってしまいやすい
例: Morrisのコンピュータ・ワーム (1988)――用意した 配列よりも大きなサイズのデータを与えられると、他の データを破壊してしまう誤りを悪用46
代表的なプログラミング言語: C++
1980年代に開発
Cにオブジェクト指向機能をとり入れた言語
オブジェクト指向以外の部分はCと同じ パーソナルコンピュータのOSやアプリケーション ソフトウェア開発の主流言語
例: Windows XP47
代表的なプログラミング言語: Java
1990年代中頃に開発
Webブラウザがダウンロードできるプログラムのための言語
として普及
互換性・安全性への配慮
現在でも安全性や互換性が求められる場面で多く用い られている
Webサーバ上のアプリケーションプログラム
携帯電話にダウンロードするアプリケーションプログラム
(e.g., Androidアプリ)
仮想機械による実行方式
見た目はCやC++に似ている
48
Cプログラムの紹介
モンテカルロ法による 円周率の計算
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(int argc, char* argv[]) { int n, m, i;
double x, y;
srand48(time(NULL));
n = atoi(argv[1]);
m = 0;
for (i = 0; i < n; i=i+1) { x = drand48();
y = drand48();
if ((x*x + y*y) < 1.0) { m += 1;
} }
printf("%f¥n", 4.0*m/n);
}
Cプログラム
def montecarlo(n) m=0
for i in 1..n x=rand() y=rand()
if x*x + y*y < 1.0 m = m + 1
end end 4.0*m/n end
def time(n)
puts Benchmark.measure{ montecarlo(n) } end
Rubyプログラム
mc.rb mc.c
複雑な処理を行うライブラリがある
(ライブラリを使う準備が必要)
乱数の生成・メッセージ表示など
変数は宣言してから使う
変数には型が付く
「int i;」=「iという名前の整数をしまう 変数を用意せよ」
値をしまうメモリの大きさを決めてお くため
計算の際に適切な機械語命令を選ぶた め
←機械語では実数と整数の足し算は違う 命令
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(int argc, char* argv[]) { int n, m, i;
double x, y;
srand48(time(NULL));
n = atoi(argv[1]);
m = 0;
for (i = 0; i < n; i=i+1) { x = drand48();
y = drand48();
if ((x*x + y*y) < 1.0) { m += 1;
} }
printf("%f¥n", 4.0*m/n);
}
49
Cプログラムの特徴
実数の表示
乱数系列の 初期化
コマンド引数 の整数変換
mc.c
50
Cプログラムを実行してみよう
1.
プログラムを作る エディタで入力(ファイル名:mc.c)
2.
コンパイルする 「ターミナル」で
gcc –O mc.c
と 入力 間違いがあるとエラーメッセージが行 番号とともに表示される
エラーが出なくなると機械語のプログ ラム(ファイル名:a.out)が作られる
3.
実行する 「ターミナル」で
./a.out
と入力す るc12345$ gcc -O mc.c
c12345$ ./a.out 1000000 3.140316
c12345$
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(int argc, char* argv[]) { int n, m, i;
double x, y;
srand48(time(NULL));
n = atoi(argv[1]);
m = 0;
for (i = 0; i < n; i=i+1) { x = drand48();
y = drand48();
if ((x*x + y*y) < 1.0) { m += 1;
} }
printf("%f¥n", 4.0*m/n);
}
mc.c
51
実行方式と速度
インタプリタとコンパイラは実行速度がどのくらい 違うか、モンテカルロ法による円周率の計算に要 する時間を比べてみよ
時間の測り方
Cの場合: time ./a.out
(ターミナルから) Rubyの場合: Benchmark.measure
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(int argc, char* argv[]) { int n, m, i;
double x, y;
srand48(time(NULL));
n = atoi(argv[1]);
m = 0;
for (i = 0; i < n; i=i+1) { x = drand48();
y = drand48();
if ((x*x + y*y) < 1.0) { m += 1;
} }
printf("%f¥n", 4.0*m/n);
}
52
コンパイル実行方式と誤り
Cプログラムに誤りを混入させ
てコンパイルし、コンパイラが どのような検査をしてくれるの かを調べてみよう
1. ここの
m = 0; をk = 0; に変え
てコンパイル(間違った変数名)2. ここの
m = 0; をm = "abc"; に
変えてコンパイル(数値のところ
に文字列) 同様の誤りをRubyプログラム に混入させると何が起きるか?
プログラムのどこに誤りがある と言われるか?
mc.c
練習
mc.c と mc.rb を書き換えて、コンパイル/実行時 のメッセージを比較してみよう。
cm12345$ gcc -O mc1.c
mc1.c: In function ‘main’:: cm12345$ irb
irb(main):001:0> load("mc1.rb")
=> true
irb(main):002:0> montecarlo(1000000)
NoMethodError: undefined method `+' for nil:NilClass
54
アセンブリ言語プログラムを 見てみよう
1. 「ターミナル」で
gcc –O –m64 –S mc.c と入力する
→mc.cがコンパイルされ、アセンブリ言 語プログラムmc.sが作られる
2. Emacs等のエディタでmc.sを見る
55
アセンブリ言語プログラム
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[]) { int n, m, i;
double x, y;
srand48(time(NULL));
n = atoi(argv[1]);
m=0;
for (i = 1; i <= n; i++) { x = drand48();
y = drand48();
if ((x*x + y*y) < 1.0) { m += 1;
} }
printf("%f¥n", 4.0*m/n);
}
movl $0, %r13d m = 0
movl $1, %ebx i = 1
L5:
call _drand48
movsd %xmm0, -40(%rbp) x = drand call _drand48
movsd -40(%rbp), %xmm1 y = drand mulsd %xmm1, %xmm1 y^2
mulsd %xmm0, %xmm0 x^2
addsd %xmm1, %xmm0 x^2 + y^2 leal 1(%r13), %eax
movsd LC0(%rip), %xmm1 1.0
ucomisd %xmm0, %xmm1 x^2+y^2 < 1.0 cmova %eax, %r13d m += 1
incl %ebx i++
cmpl %ebx, %r12d i <= n
jge L5
L4:
mc.sの一部
機械語にすると どんな命令になるか?
56
おまけ: アセンブリ言語の
プログラムを書き換えてみよう
1. エディタを使ってmc.sの途中にある
「ucomisd %xmm0, %xmm1」を
「ucomisd %xmm1, %xmm0」に書き換える
•
意味: 比較するものの順序を入れ替える→モンテカルロ法の不等号を逆にしたことに相当