MATLAB基本操作復習 先日のExcelの例題 x y 0.278 0.398 0.522 0.743 0.911 0.937 1.022 1.398 1.521 1.843 (1) xとyを単純にプロットする 2.4739 3.6955 4.1761 5.499 7.124 7.4567 8.2219 12.481 13.69 18.079 ← 「散布図」のグラフを描いてみる (2)近似直線をあてはめる ● これと同じ作業をMATLABで やってみる。 MATLABのホームタブ、変数メ ニュー、新規変数で表示される シートに、Excelから10個の点の データをコピーペースとして変数名 を付けるだけ。 プロットタブでtestdataの散布図 • 変数testdataをマウスで選び、プロットタブで scatter(散布図)を描くだけ。コマンドでやるな らscatterコマンドを使う。 Figureウィンドウのツールメニュー • データの統計 • 基本的な近似 • 以上、簡単でした。TeXの大レポートのグラフは、 MATLABで描いても良いです。 • グラフの細かい調整はplottoolsで行います。 • ヘルプの「プロットツール」を見て下さい。「グラフ の注釈」も見て下さい。グラフ資料の作り方の参 考になります。 >> testdata testdata = 0.2780 0.3980 0.5220 0.7430 0.9110 0.9370 1.0220 1.3980 1.5210 1.8430 2.4739 3.6955 4.1761 5.4990 7.1240 7.4567 8.2219 12.4810 13.6900 18.0790 >> x=testdata(:,1) >> y=testdata(:,2) x= y= 0.2780 0.3980 0.5220 0.7430 0.9110 0.9370 1.0220 1.3980 1.5210 1.8430 2.4739 3.6955 4.1761 5.4990 7.1240 7.4567 8.2219 12.4810 13.6900 18.0790 コマンドで行う場合 観測データプロットと近似式あてはめ >> y=[2.4739 3.6995 4.1761 5.599 7.124 7.4567 8.2219 12.481 13.69 18.079] >> x=[0.278 0.398 0.522 0.743 0.911 0.937 1.022 1.398 1.521 1.843] >> plottools プロットツールを起動 散布図 oは、アルファベット小文字オー >> plot(x,y,'o') 1次式(直線)近似の当てはめ結果 >> p=polyfit(x,y,1) 1次の多項式p y=9.7340x-1.0183 p = 9.7340 -1.0183 >> plot(x, polyval(p,x), '-', x,y,'o') グラフ描画 * polyval(p,x)は多項式pの定義域xに対する値域のベクトル つまり、近似直線上の値 plotコマンド • • • • 2次元線形プロット関数 plot(y) yの配列番号を横軸、yを縦軸に plot(x,y) xを横軸、yを縦軸に plot(x,y,仕様指定) 仕様指定で線種、マーカ、色を指定 • plot(x,y,仕様指定, ‘LineWidth’,線幅ポイント数) 線幅も指定 仕様指定 • 線種、マーカ、色指定の3組をシングルクォー ト「’」で囲む 。 ’-*r’ は、赤い色で実線でアスタ リスクを結ぶ。 • 線種: 「-」実線、「:」点線、「-.」鎖線、「--」破線 • マーカ: 「.」「o」「x」「+」「*」「s」四角形「d」ダイ ヤ「^」「v」「>」「<」上下左右矢印「p」五角形「h」 六角形 • 色: 「y」黄「m」マゼンタ「c」シアン「r」赤「g」緑 「b」青「w」白「k」黒 ひとつのfigureウィンドに複数のグラフ • plot(x1,y1,x2,y2,・・・) (xn,yn)の組み合わせで複数のグラフを描く • plot(x1,y1,仕様1,x2,y2,仕様2,・・・, ‘LineWidth’,線幅ポイント数) • hold onコマンドを使う方法 hold on plot(・・・) plot(・・・) 2次元線形以外のプロット • • • • • loglog(x,y) semilogx(x,y) semilogy(x,y) polar(theta,r) bar(x,y) 両対数プロット x軸対数 y軸対数 極座標 棒グラフ 3次元プロットは、メッシュプロットや表面プロット グラフの装飾や調整 • • • • • title(‘文字列’) xlabel(‘文字列’) ylabel(‘文字列’) text(x, y, ‘文字列’) axis([xmin, xmax, ymin, ymax]) *FigureウィンドウのGUIツールでもできる。 GUIとCUI • 散布図を描いて近似直線を引く、はマウスを 使ってもできるし、コマンドでもできることが分 かった。 • マウスでできるなら、わざわざコマンドを打っ てやることはない(コマンドは知っていないと 打てないから)、だろうか? コンピュータリテラシ 第14回 MATLAB(2a) コンピュータでの数値計算:数値の表現と扱い 今日のテーマ: コンピュータによる数値情報の扱い コンピュータの演算処理速度 • コンピュータの演算性能の目安 ← 1秒間に実行できる浮動小数点演算(実数 どうしの計算)の回数 単位 FLOPS (floating-point operations per second) コンピュータが扱う数値 • コンピュータが扱う数値(数値とは「計算の対 象になるもの」)は2種類 整数型数値 : 小数点がつかない 実数型数値 : 小数点がつく • 整数と実数といっても数学で習ったのとは異 なる 整数は実数に含まれるものではない 数値もコンピュータの中では有限桁の2進数 で表される → 扱える範囲が有限 整数型数値 • 正の整数と負の整数を表すため、2の補数表 現を用いると便利 1bit 0 31bits 00・・・・・・・・・・・・・・・・・・・・・・・・・・・・・0 正数については、その数の大きさ 負数については、その数の2の補数 その整数の符号 符号は、1のとき負の数 2の補数は、その数を2進数で表し、すべてのビッ トの0と1を反転させて1を足した数 2の補数表現 • 3bitsの場合 011 = 3 010 = 2 001 = 1 000 = 0 111 = - 1 110 = - 2 101 = - 3 100 = - 4 正の数と負の数の足し算、負の数と負の数の足し算が、(負数 を2の補数表現すれば)通常の2進数の足し算としてできる! 4bitsで表せる整数の範囲 0111 正の整数の最大値 1111 0110 1110 0101 1101 0100 1100 0011 1011 0010 1010 0001 1001 0000 1000 負の整数の最大値 正の数と負の数の足し算、負の数と負の数の足し算が、(負数 を2の補数表現すれば)通常の2進数の足し算としてできる! 正整数の最大値に1を足すと負整数の最大値になる。。。 2の補数表現 • 4bitsの場合 - 8~7の範囲の整数 • 8bitsの場合 -128~127の範囲の整数 • コンピュータで扱う整数は、32bitsや64bits 表せる範囲の整数を越えて計算しようとする→ 桁あふれ(オーバーフロー)という現象 整数は、コンピュータ内で数えたり、(文字コード のように)区別したりするのに使う。 計算には向かない。 実数型数値 • 仮数部と指数部を分けて表す浮動小数点形 式で表現 → 大きな数も小さな数も表現して計算できる • 仮数部の有効桁数は決まっているので、近 似値しか表せない • (例)10進数の浮動小数点形式で、仮数部4 桁(=有効数字)、指数部2桁が使えるなら、次 の範囲の数を表せる - 9.999×1099 ~ +9.999×1099 IEEE754規格の倍精度(64bits)実数 1bit 0 11bits 52bits 00・・・・・・0 00・・・・・・・・・・・・・・・・・・・・・・・・・・・・・0 仮数部 : 2進52桁は、10進数の15桁くらいの有効数字 指数部(符号含む) 仮数部の符号 符号は、1のとき負の数 Mathematicaはがんばる • Mathmaticaでは、厳密整数や浮動小数点数の 桁数に制約がない。 • それはMathematicaが異常、すごくがんばってい る。 • 普通は、コンピュータでの計算結果は疑わしいと 思って下さい^^; • それが証拠に、Excelだって、3.3-3.2もちゃんと計 算できません ← セルの書式設定で、数値の 有効桁数いくつ以上から計算結果がおかしくな るか観察してみましょう。 誤差と精度に対する考え方 • 計算や計測などで「本当の値とのずれ」のこ とを誤差と呼ぶ • 絶対誤差: 誤差の絶対的な量がどれくらいか • 相対誤差: ある値について、誤差がどれくらい 含まれているか たとえば「絶対誤差が1度の温度計」があったものとする。 室温(20度とか)を計測 → 相対誤差 5% → ぼろい 熔融金属(1000度とか)を計測 → 相対誤差 0.1% → 優秀 有効数字 • 精度: 「どれくらい正確か」を表す言葉だが曖昧 • 有効数字(有効桁数): 「数字が何桁正しいか」 先の例で 23±1度 → 有効数字1桁 1042±1度 → 有効数字3桁 • 倍精度実数型の場合、有効数字は10進数16桁 くらい。優秀だと思いますか? 「2進の」「浮動小数点」表現での数値計算 → さまざまな気をつけるべき状況 実数計算の精度 • 有効桁数が決まっていることで、実数の計算では精 度が落ちることがある (例)今日のポイント! ・ 10で割ったり、0.1を掛けるのは、(人にとっては容 易な計算だが、)0.1は2進表現では循環小数になる ためコンピュータは精度を落とす計算 ・ 実数どうしの計算の精度で、桁数がすごく大きな数 どうしや、すごく大きな数と小さな数を計算するときは (すべての桁の数が扱えず)桁落ちするのを観察しよ う 今日のポイント! 数値計算するとき • 計算には、(整数でなく)倍精度実数を使って いる • 計算問題は、人が計算する方法と、計算機に 解かせる方法とでは、かなり違うことがある (コンピュータなら無理やり力ずくで計算するこ とも可能で頼もしい、一方で人の予想外とこ ろで容易に計算精度を落とすことがある) • コンピュータの計算には、誤差を回避する工 夫が必要なことがある コンピュータの計算結果は、すべて近似計算と思え。 本日のMATLAB実習 (1) MATLABで計算誤差について観察・体験しよ う。コンピュータでの計算結果が誤差まみれ (になりかね)な(い)ことをぜひ体験しておきま しょう。 (2) 円周率の値の近似値を複数の方法で求めて みる計算などを例題に用いています。 (3) そのために、MATLABで簡単なプログラムを動 かします。プログラムの中身に興味のある人は それも見て下さい。 * Mathematica、R、Excelも、プログラミングの機能を備えています。 準備1 (1) ドキュメントのMATLABフォルダ内にrenshuフォルダを 作っていない人は、先に作りましょう。 (2)クラスのページのリンクから圧縮フォルダmatfunc.zipをダ ウンロードし中身のファイルを確認しましょう(.mファイルが5 つ)。 (3)5つのファイルをMATLAB/renshuフォルダにコピーしま しょう。 準備2 ●MATLAB起動 ●カレントディレクトリをrenshuフォルダに移る。 (先ほど保存した.mファイル5つがあることを 確認) 本日の教科書 MATLAB/Scilabで理解する数値計算、櫻井鉄也著、 東京大学出版会、ISBN978-4-13-062450-3 • 1章~2章を使用。主に「第2章 有限桁の数 値」のところの内容がコンピュータの数値計 算の「基本のき」を取り扱っています。 • MATLABはプロプライエタリソフトですが、 scilabはMATLABと互換性の高いフリーソフト です(構文が違うところも多そうですが、比較 しながら使えるようです)。 MATLABプログラミング ~分岐の基本構文~ • 条件分岐の基本構文 if 式 命令 end 「式」は条件式で、式が成り立って いるとき「命令」実行する。ifを打っ てからendを打つまでは、改行しな がら命令を書いてよい。 >> k=5 >> if k>0 disp(k) end if 式 命令 elseif 式 命令 else 命令 end 式が成り立たないときは、elseifで 次の条件式で判定する。それを1 回以上繰り返した後、最後までど の条件式も成り立たなかった場合 を扱うにはelseを用い(省略も可)、 if文はendで終わる。 MATLABプログラミング ~繰り返しの基本構文~ • 繰り返しの基本構文 for ループ変数 = ループ変数の範囲 命令 end ループ変数の値を「範囲」で変化さ せながら「命令」繰り返し実行する。 ループ変数の変化の範囲は、ベク トルで与える。 >> for k=1:10 disp(k) end >> v=5:-1:1 >> v >> for k=v disp(k) end while 条件 命令 end 条件が成り立つ間、「命令」を繰り返 し実行する。「命令」を実行したら、 また条件を調べる、というようにして。 >> a=10; >> while a>=1; disp(a); a=a/2; end MATLABプログラミング ~ ファンクションMファイル(入出力あり) ~ • 関数(ファンクションMファイル)の定義 >> edit func.m エディタでfuncの関数定義を書き保存する。func.mのあるディ レクトリでは関数funcを(読み込まなくても)利用できる。キー ワードfuncionを使って定義する関数には、入力を渡して実行 し、出力を受け取ることができる。 ● func.mの中身を打ち込もう 以下のように使う。 >> [C, d] = func(3, sqrt(2)) function[A,b]=func(x,y) A=eye(2,2)*x; b=[y;y^2]; プログラミング ~ スクリプトMファイル(入出力なし) ~ • 関数(スクリプトMファイル)の定義 >> edit enshuritu.m エディタでMATLABインタプリタに打つものをmファイルに書い ておき、実行することができる。実行時に入力は渡せない。 >> enshuritu n=[100 1000 10000 100000 1000000]; m=length(n); for k=1:m z=rand(n(k),2); r=z(:,1).^2+z(:,2).^2; p(k)=sum(r<1)/n(k)*4; end; disp(p); 乱数によるπの値のシミュレーション を例題に。 • 1×1のマス内に点(x,y)を0~1の一様乱数で 沢山打つものとする • 打った点が1/4円内に入る確率や回数は、外 側の面積1の正方形と1/4円の面積π/4の比 に従う • 打った点が1/4円内に入る確率 ~ 「1/4円の 面積÷全体の面積」 = π/4 • これを利用してπを求めてみよう y 1 0 1 x enshuritu.m • 乱数を使って円周率の近似値を求める。試行 回数をn= 100, 1000, 10000・・・と増やすと真 の円周率の値に近づくのが分かる。 n=10(10回乱数を発生)の場合だと、こんな計算をやっている >> z=rand(10,2) 10個分の点の座標(x,y),0=<x,y<1のデータを乱数で生成 >> z(:,1) >> z(:,1).^2 「.」(ピリオド)は行列の要素ごとに演算を行うのでした >> r=z(:,1).^2+z(:,2).^2; 10個の点それぞれの原点からの距離を計算し、 >> r >> p=sum(r<1)/10*4; >> p その距離が1より小さいものを合計する。その合計は、nが大 きくなると半径1の1/4円の面積(π/4)と、外側の一辺が1の正 方形の面積(1)の比に近づくことを利用してπの値を計算する 他のプログラミング言語でやると public class Test { public static void main(String[] args) { int n = Integer.parseInt(args[0]); int count = 0; for(int i = 0; i < n; ++i) { double x = Math.random(), y = Math.random(); if(x*x + y*y <= 1.0) ++count; } System.out.printf("%.20g¥n", 4.0 * count / n); } } 乱数発生(サイコロを振る)回 数が増やしてみた。乱数の値 は毎回違うからこんなもの。C MATLABのプログラムは簡潔に書ける から好き、という人が多いらしい > java Test 1000 3.1400000000000000000 > java Test 10000 3.1308000000000000000 > java Test 100000 3.1414400000000000000 > java Test 1000000 3.1408160000000000000 コンピュータは力任せに、 そもそも近似計算をする道具 • コンピュータはいくら計算しても疲れないので、 連続量をサンプリングする精度を細かくして いったり(細かくしても誤差はあるので、このと き真の値との間に生じる誤差を量子化誤差と いう)、シミュレーションの試行回数を多くする ような計算に用いることが多い。 そもそもの近似計算:量子化 • 本来連続的なものを「個数」に置き換える(サ ンプリング、標本化に伴う)ことの誤差を『量 子化誤差』という • 多くの場合、量子化誤差はアナログ量をディ ジタル量に変換するところで現れる • たとえば「0.1kg単位で表示されるデジタル体 重計」は50gの量子化誤差 量子化誤差の例 • 「半径1mの円の面積=π(m2)」のはずだから、 • 「2m四方の紙を1cm単位に分けて、円内に 入っているものの数を数える」ことで面積が求 まるはず。 • 上下/左右対称だから1/4円についてやって4 倍する ← 実際この方法でπの値を求めてみると、 1m N 1m ・ ・ ・ 2 1 1マス 1 2 ・・・ N 1/n×1/n (cm2) enshurituR.m n=[100 1000 10000]; m=length(n); for k=1:m count=0; for x=0:n(k)-1 for y=0:n(k)-1 if x*x+y*y<=n(k)*n(k) count=count+1; end; end; end; p(k)=4*count/(n(k)*n(k)); end; disp(p); 乱数を使うenshuritu.m は毎回結果が違うが、こ ちらは毎回同じ結果 個数を増やして近似(→ 精度を上げる)すればす るほど、真の値に近づく ただし精度を上げすぎてもあまり 意味がないこともある テーマ: サイコロを振る シミュレーションと大数の法則 そもそもの近似計算: ・乱数を使ってのシミュレーションに基づく数値は、乱数を 使っているからもともと毎回違う誤差がある(この誤差に特に 名前はついていない) ・ただ、「サイコロを振る回数Nを増やすと正確な値に近づく (大数の法則)」 ・誤差は 1/√N に比例(中心極限定理) ・実際にNを増やしながら試してみよう(100倍にすると誤差が 1/10になるか) • このような、「サイコロを振って値を求める」方 法もさまざまなところで使われている。『モン テカルロ法』 大数の法則(サイコロシミュレーション) • saikoro.mで、大数の法則の様子を見てみよう • サイコロの目が1/6の確率で出るというような 確率も、試行回数を増やすとゆらぎながらそ の値に近づく。 • このスクリプトMファイルの出典。 「信号処理」「画像処理」のためのMATLAB入 門、高井信勝著、工学社、ISBN978-4-875933C3055 二進数による実数の表現 を見てみよう! 2進の浮動小数点による数の表現 >> f=[1 1]; >> f .* 0.5 .^(1:length(f)) >> sum(f .* 0.5 .^(1:length(f))) 0.11(2)= (1/2)+(1/2)^2 >> f=[0 1 0 1 0 1]; >> f .* 0.5 .^(1:length(f)) >> sum(f.*0.5.^(1:length(f))) 0.010101(2) コンピュータ内部での実数は、2進の指数表現。 1.1(2) × 2-1 仮数部が、「1.-----」(小数点より左が必ず1になるよ うな形)に正規化した後に、数の大きさを指数部で表 している。 1.0101(2) × 2-2 IEEE754規格の倍精度(64bits)実数 1bit 0 11bits 52bits 00・・・・・・0 00・・・・・・・・・・・・・・・・・・・・・・・・・・・・・0 仮数部 : 2進52桁は、10進数の15桁くらいの有効数字 指数部(符号含む) 仮数部の符号 符号は、1のとき負の数 次の計算を打ち込んでやってみよう 何が起きたか、考えよう 浮動小数点による数の表現の限界による誤差 オーバーフロー、アンダーフロー >> realmax 最大の数 >> realmin 最小の数 realmaxやrealminの周辺で起きる >> (1e150)^2 >> (1e200)^2 無限大 >> 1/Inf ゼロ オーバフローとアンダーフローを観察 >> (1e-150)^2 >> (1e-200)^2 ゼロ >> 1/(1e-200)^2 無限大 実数の丸め誤差による計算結果の狂い >> x=1; <= x=1からはじめ て、 1+xが1と等し くない間xを半分に していく。 >> while (1+x ~= 1) x=x/2; end >> x x= 1.1102e-016 <= While文が停止した時の x の値??? 実数の丸め誤差:0.1の2進表記 • 10進の0.1は、2進表 記ではどのように表せ るか、自分で手計算し てみよう。 • コンピュータでの実際 のdouble型実数0.1が どのように表されてい るか、bitex.mで調べよ う。 >> bitex(0.1) ans = 1001100110011001100110011001100 110011001100110011010 「bitex(数値)」は、その数値が倍精度実数で表 現されたときの仮数部の52ビットぶんを見 せてくれます。 0.1の二進表現に係わる 計算の狂い >> x=0.1; >> while x<1 x=0.1からはじめて、x が 1 より小さい間 0.1を足す計算のはずが・・・ x = x + 0.1; disp(x); disp(bitex(x)); end ●上のwhile文を実行したら、どんなまずい事が起るか。 また、なぜそんな事になるのか簡単に説明せよ。 fl.m • 関数flは、数値xを10進の有効桁数5桁に丸め る関数である。 使用例: >> pi >> format long >> pi >> fl(pi) ←有効桁5桁 • 倍精度実数計算ではだいたい10進数16桁の 有効桁数であるが、何桁であっても有限桁数 が決まっていればそれによる誤差が生じること を関数flを使って観察しよう。 有効桁数に伴う情報落ち >> x1=121730; x2=3.1481; >> x1+x2 ans = 1.217331481000000e+005 有効桁数16桁の正しい答え >> fl(x1+x2) ans = 121730 赤: 誤差の大きな結果 有効桁数が5桁しかないと、結果は こうなる。x2の値は無いのと同じ。 >> a=8.1651; b=8.1653; 有効桁限界あたりの怪しい計算 例: 2数の平均 >> (a+b)/2 ans = 8.16520000000000 正しい答え 同じ計算を有効桁数5桁 ですると、誤差が大きい >> fl(fl(a+b)/2) ans = 有効桁数5桁でも工夫に よって正しい答え >> fl(a+fl(fl(b-a)/2)) ans = 平均値であり得ない値! 8.165200000000001 8.164999999999999 赤: 誤差の大きな結果。なぜ誤差 が大きいのか? 緑:計算の工夫によって正しい答え に近い値。どういう工夫をしたのか? 中間結果のオーバフロー >> a=2.0e200; >> b=1.0e200; >> c=a^2 + b^2 c= Inf cは非常に大きな値のため オーバーフロー C= 𝑎2 +𝑏 2 を計算することはで きないのか?
© Copyright 2024 ExpyDoc