-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy path2.html
More file actions
1142 lines (1042 loc) · 42.3 KB
/
2.html
File metadata and controls
1142 lines (1042 loc) · 42.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>プログラマの為の数学勉強会</title>
<!-- For reveal.js -->
<link rel="stylesheet" href="lib/reveal/css/reveal.css">
<link rel="stylesheet" href="lib/reveal/css/theme/night.css">
<link rel="stylesheet" href="lib/reveal/lib/css/ir_black.css">
<!-- For Graphics -->
<link rel="stylesheet" href="css/graphics.css">
<style>
.reveal .chapter-title {
margin-top: 3em;
}
.reveal {
font-size: 32px;
line-height: 1.4em;
}
.reveal .slides {
text-align: left;
}
.reveal section img {
border: none;
background: 0;
margin-left: 1em;
margin-right: 1em;
box-shadow: none;
}
.reveal strong {
color: #ffff66;
}
.reveal sup {
font-size: 40%;
}
.reveal table {
margin-top: 0.5em;
margin-bottom: 0.5em;
border: 2px solid lightblue;
}
.reveal pre {
font-size: 0.7em;
}
.reveal pre code {
max-height: 600px;
}
.reveal .note {
font-size: 50%;
}
.reveal .controls div.navigate-up,
.reveal .controls div.navigate-down {
display: none;
}
.reveal .block {
border: solid 2px;
position: relative;
border-radius: 8px;
margin-top: 0.8em;
margin-bottom: 0.8em;
padding: 1em 0.8em 0.5em 0.8em;
}
.reveal .block:after {
content: "";
display: block;
clear: both;
height: 1px;
overflow: hidden;
}
.reveal .answer {
color: #111111;
}
.reveal .block h4 {
position: absolute;
top: -0.5em;
margin: 0 auto;
background: #111111;
font-weight: bold;
}
</style>
<!-- Setup libraries for RequireJS-->
<script src="lib/require.js"></script>
<script>
requirejs.config({
baseUrl: "js",
paths: {
d3: "../lib/d3/d3.v3.min",
numeric: "../lib/numeric-1.2.6",
MathJax: "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS_HTML"
},
shim: {
d3: { exports: "d3" },
numeric: { exports: "numeric" },
MathJax: { exports: "MathJax" }
}
});
</script>
<!-- Initialize MathJax -->
<script type="text/x-mathjax-config">
require(["MathJax"], function (MathJax){
MathJax.Hub.Register.StartupHook("AsciiMath Jax Config", function () {
var AM = MathJax.InputJax.AsciiMath.AM;
AM.symbols.push(
{input:"mathbi",tag:"mstyle",atname:"mathvariant",atval:"bold-italic",
output:"mathbi",tex:null,ttype:AM.TOKEN.UNARY}
);
});
MathJax.Hub.Config({
showProcessingMessages: false,
skipStartupTypeset: false,
tex2jax: {
inlineMath: [ ["\\(","\\)"] ],
displayMath: [ ["\\[","\\]"] ]
}
});
});
</script>
</head>
<body>
<div class="reveal">
<div class="slides">
<section style="text-align: center">
<h1> プログラマの為の<br>数学勉強会<br>第2回</h1>
<span>
(於)ワークスアプリケーションズ<br>
中村晃一<br>
2013年9月19日
</span>
</section>
<section>
<h2>謝辞</h2>
<p>
この会の企画・会場設備の提供をして頂きました<br>
㈱ ワークスアプリケーションズ様<br>
にこの場をお借りして御礼申し上げます。
</p>
</section>
<section>
<h2> この資料について </h2>
<p>
<ul>
<li> <a href="http://nineties.github.com/math-seminar">
http://nineties.github.com/math-seminar
</a>に置いてあります。 </li>
<li> SVGに対応したブラウザで見て下さい。主要なブラウザで古いバージョンでなければ大丈夫だと思います。</li>
<li> 内容の誤り、プログラムのバグは<a href="http://twitter.com/9_ties">@9_ties</a>かkoichi.nakamur AT gmail.comまでご連絡下さい。</li>
<li> サンプルプログラムはPythonで記述しています。 </li>
</ul>
</p>
</section>
<section>
<h2 class="chapter-title"> 浮動小数点数と誤差 </h2>
</section>
<section>
<h2> 浮動小数点数と誤差 </h2>
<p>
浮動小数点数を利用した計算結果には誤差が含まれます。
<strong>複雑な計算</strong>をしたり<strong>多数のデータ</strong>を扱う場合にはその影響が目に見えて現れますので,
最初に浮動小数点数と誤差に関する基礎知識の確認を行います。
</p>
</section>
<section>
<h2> 浮動小数点数の規格 </h2>
<p>
最も広く使用されている浮動小数点数の規格は<strong>IEEE 754</strong>です。
</p>
<p>
以下のデータ形式に加え,丸めの方式などが定義されています。
</p>
<ul>
<li> 正規化数 </li>
<li> 非正規化数 </li>
<li> \(0\)と\(-0\) </li>
<li> \(\infty\)と\(-\infty\) </li>
<li> 非数(NaN) </li>
</ul>
<p>
IEEE754では3種類の二進小数,2種類の十進小数の形式が基本形式として定義されていますが,以下では二進形式のみ説明をします。
</p>
</section>
<section>
<h2> 正規化数 </h2>
<p>
二進形式の<strong>正規化数</strong>は
</p>
<ul>
<li> <strong>符号\(s\)</strong> (1bit)</li>
<li> <strong>指数\(e\)</strong> (整数)</li>
<li> <strong>仮数\(1.m_1m_2\cdots m_n\)</strong> (1以上2未満の有限二進小数)</li>
</ul>
<p>
からなり,
\[ (-1)^s\times 1.m_1m_2\cdots m_n \times 2^e \]
という形で表されます。
</p>
<div class="block" style="border-color:lightgreen">
<p>
例えば,小数の\(1001.01001_2 = 9.28185_{10}\)は
\[ 1.00101001\times 2^3 \]
と正規化され,符号\(0\),指数\(3\),仮数\(1.00101001_2\)となります。
</p>
</div>
</section>
<section>
<h2> 二進小数の精度・範囲 </h2>
<p>
二進小数については単精度,倍精度,四倍精度という3種類の精度の形式が定義されています。
</p>
<table>
<tr align="center">
<td> </td> <th> 指数の範囲 </th> <th> 仮数の桁数(<strong>精度\(p\)</strong>) </th>
</tr>
<tr align="center">
<th> 単精度(binary32形式) </th> <td> -126~127 </td> <td> 1 + 23 </td>
</tr>
<tr align="center">
<th> 倍精度(binary64形式) </th> <td> -1022~1023 </td> <td> 1 + 52 </td>
</tr>
<tr align="center">
<th> 四倍精度(binary128形式) </th> <td> -16382~16383 </td> <td> 1 + 112 </td>
</tr>
</table>
<p>
\(\log_{10}2 \approx 0.3010\)をこれらに掛ければ十進数でのおおよその精度・指数の範囲が解ります。例えば倍精度の場合,仮数の精度は十進数で\(15\)~\(16\)桁程度,指数は\(10^{-308}\)から\(10^{308}\)程度の範囲となります。
</p>
</section>
<section>
<p>
好きな処理系で精度・指数の限界について実験してみると良いでしょう。
以下は,Python 2.7.3(デフォルトでは倍精度)の例です。
</p>
<pre><code class="python">>>> 1.0 + 1e-15
1.000000000000001
>>> 1.0 + 1e-16 # 仮数の精度より細かくは値を表現出来ない
1.0
>>> 1e308
1e+308
>>> 1e309 # 指数のオーバーフロー
inf
>>> 1e-307
1e-307
>>> 1e-308 # 非正規化数(後述)に切り替わり0.0にはならない
1e-308
>>> 1e-323
1e-323
>>> 1e-324 # 指数のアンダーフロー
0.0
</code></pre>
</section>
<section>
<h2> 非正規化数 </h2>
<p>
正規化数の
\[ (-1)^s\times 1.m_1m_2\cdots m_n \times 2^e \]
という表現では0周辺の値の扱いに問題が発生します。
</p>
<div class="block" style="border-color:lightgreen">
<p>
十進小数の方が分り易いので,\(a = 1.1\times 10^e\)と\(b = 1.0\times 10^e\)を考えます。これらの差をとって正規化すると
\[ a - b = 0.1\times 10^e = 1.0\times 10^{e-1} \]
となり指数が減ってしまいます。<strong>\(e\)が指数の範囲の最小値の時は\(e-1\)がアンダーフローする</strong>ので,\(a \neq b\)なのに\(a - b = 0\)となってしまいます。
</p>
</div>
</section>
<section>
<h2> 非正規化数 </h2>
<p>
そこで,0の周辺では正規化をせず
\[ (-1)^s\times \color{pink}{0}.m_1m_2\cdots m_n \times 2^{\text{最小指数}} \]
という固定小数点数で表すことにします。これを<strong>非正規化数</strong>と言います。指数のアンダーフローが無くなる替わりに,仮数の有効桁数が減少するので注意してください。
</p>
<p>
これによって,例えば倍精度の場合は
\[ 0.000\cdots0001\times 2^{-1022} = 2^{-1074} \approx 4.941\times 10^{-324} \]
という所まで表せる事になります。
</p>
</section>
<section>
<h2> マシンイプシロン </h2>
<p>
精度\(p\)の正規化数では<strong>\(\epsilon = \frac{1}{2^{p-1}}\)</strong>
より小さい仮数の差を表現出来ません。この\(\epsilon\)は<strong>マシンイプシロン</strong>と呼ばれます。<sup>注</sup>
</p>
<div align="center"> <div> <img width="700px" src="fig/machine-epsilon.png"></div> </div>
<div align="center">
<table>
<tr align="center">
<th> 単精度 </th> <td> \(\epsilon = 2^{-23} \approx 1.19\times 10^{-7}\) </td>
</tr>
<tr align="center">
<th> 倍精度 </th> <td> \(\epsilon = 2^{-52} \approx 2.22\times 10^{-16}\) </td>
</tr>
<tr align="center">
<th> 四倍精度 </th> <td> \(\epsilon = 2^{-112} \approx 1.93\times 10^{-34}\) </td>
</tr>
</table>
</div>
<p class="note">
注: マシンイプシロンはIEEEで定義されている訳ではなく様々な定義が存在しますが,ここでは
「\(1\)より大きい最小の浮動小数点数が\(1+\epsilon\)と表される時の\(\epsilon\)」という事にします。
</p>
</section>
<section>
<h2> 丸め</h2>
<p>
計算機は内部的に多めの桁数で演算を行ったあと,実際の桁数に収まるように結果を丸めます。
</p>
<p>
IEEEではいくつかの丸めの方式が定義されていますが,<strong>再近接偶数丸め</strong>が標準的な方式です。
</p>
<div class="block" style="font-size:90%;border-color:pink">
<h4 style="color:pink">再近接偶数丸め</h4>
<ul>
<li> 最も近い値へ丸める </li>
<li> ちょうど中間の値は結果が偶数となるように丸める </li>
</ul>
<div align="center"> <div> <img width="700px" src="fig/rounding.png"></div> </div>
</div>
</section>
<section>
<h2> 何故,偶数丸め? </h2>
<p>
中間の値の丸めを切り上げ,切り捨ての一方に定めると誤差の出方の偏りが生じてしまいます。偶数丸めを行うことによって誤差の累積を抑える事が出来ます。
</p>
<div class="block" style="border-color:lightgreen">
<p>
十進小数の四捨五入を例に説明します。整数\(x\)と\(x+1\)の間の9つの小数
\[ x.1,\ x.2,\ x.3,\ x.4,\ x.5,\ x.6,\ x.7,\ x.8,\ x.9\]
を四捨五入すると4つが切り捨て,5つが切り上げとなります。
</p>
<p>
自前で丸めを行う場合には,処理系の用意する丸め関数の仕様をよく調べるようにしましょう。
</p>
</div>
</section>
<section>
<h2> 絶対誤差と相対誤差 </h2>
<p>
実数\(x\)とその近似値\(\widetilde{x}\)に対して
\[ E_A(x) = |x-\widetilde{x}| \]
を<strong>絶対誤差</strong>と言います。
</p>
<p class="fragment" data-fragment-index="1">
一方,浮動小数点数だと誤差は仮数部に現れるので,その大きさは<strong>相対誤差</strong>
\[ E_R(x) = \frac{|x-\widetilde{x}|}{|x|} \]
によって評価する事が出来ます。<sup>注</sup>
</p>
<p class="note fragment" data-fragment-index="1">
注: \(x=0\)の時には\(E_R(x)\)が定義されないので,絶対誤差を用いて議論する必要があります。
</p>
</section>
<section>
<h2> 丸めの相対誤差 </h2>
<p>
\(f\times 2^e\)を\(\widetilde{f}\times 2^e\)で近似した場合の相対誤差は
\[ \frac{|f\times 2^e-\widetilde{f}\times 2^e|}{|f\times 2^e|} = \frac{|f-\widetilde{f}|}{|f|} \]
となります。
</p>
<p class="fragment">
仮数の間隔は\(\epsilon\)なので,再近接丸めの場合\(|f-\widetilde{f}|\leqq \frac{\epsilon}{2}\)が成り立ちます。また\(1\leqq |f| < 2\)なので
\[ \frac{|f-\widetilde{f}|}{|f|} \leqq \frac{\epsilon}{2} \]
となります。これが丸めの相対誤差の上限となります。
</p>
</section>
<section>
<h2> 丸め以外の誤差 </h2>
<p>
丸め以外にも以下のような要因によって誤差が生じます。これらは丸め誤差よりも影響が大きいので十分に気をつけなければいけません。
</p>
<ul>
<li> オーバーフロー・アンダーフロー </li>
<li> 情報落ち </li>
<li> 桁落ち </li>
<li> 打ち切り誤差 </li>
<li> 二進と十進の変換 </li>
</ul>
</section>
<section>
<h2> オーバーフロー・アンダーフロー </h2>
<p>
指数がオーバーフローすると\(\pm \infty\),アンダーフローすると\(\pm 0\)になってしまいます。仮数の一切の情報が失われてしまうので,発生させないように十分気をつける必要があります。
</p>
<div class="block fragment" style="border-color:pink">
<h4 style="color:pink"> 対処 </h4>
<p>
オーバーフロー・アンダーフローは<strong>巨大な数・微小な数の乗除累乗算</strong>などによって発生します。典型的な回避方法は<strong>対数</strong>を利用する事です。
\[ \begin{aligned}
\log AB &= \log A + \log B \\
\log \frac{A}{B} &= \log A - \log B \\
\log A^k &= k\log A
\end{aligned} \]
</p>
</div>
</section>
<section>
<h2> 確率計算からの事例 </h2>
<p>
確率\(p_1,p_2,\cdots,p_n\)で生じる独立な事象が,全て生じる確率(同時確率)は
\[ P = \prod_{i}p_i = p_1p_2\cdots p_n \]
となります。\(0\leqq p_i \leqq 1\)なので,\(n\)が大きいと容易にアンダフローを起こします。
</p>
<p>
これを回避する為には
\[ \log P = \sum_{i}\log p_i = \log p_1 + \log p_2 + \cdots + \log p_n \]
と計算すれば良いです。
</p>
</section>
<section>
<p> 計算例 </p>
<pre><code class="python">>>> from math import log10
>>> from random import random
>>> ps = [random() for i in range(1000)] # 1未満正数を1000個用意
>>> P = 1.0
>>> for p in ps:
... P *= p
...
>>> P
0.0 # アンダーフロー発生
>>> logP = 0.0
>>> for p in ps:
... logP += log10(p)
...
>>> logP
-428.5221443182958 # アンダーフロー回避
>>> 10**(logP - round(logP))
3.005077533929242 # つまりPの値は約3.0e-429
</code></pre>
</section>
<section>
<h2> 桁落ち </h2>
<p>
<strong>非常に近い2数の差</strong>を取ると,有効桁数が大きく減少してしまう現象です。
</p>
<pre><code class="python">>>> 1.2345678 - 1.2345677
1.0000000005838672e-07 # 10桁しか合っていない
</code></pre>
<div class="block fragment" style="border-color:lightgreen">
<p>
有効桁数が4桁の十進小数\(1.234\times 10^2\)と\(1.233\times 10^2\)を用いて説明します。
\[ 1.234\times 10^2 - 1.233\times 10^2 = 1\times 10^{-1} \]
となり有効桁数が1桁に落ちてしまいます。
</p>
<p>
足りなくなった桁は計算機内部で余分に持っている桁の数値で埋めるので,上のように一見デタラメな数値が出てきます。
</p>
</div>
</section>
<section>
<h2> 桁落ちの対処 </h2>
<p>
数式の変形によって回避出来る場合があります。いつでも出来る訳ではないので,必要ならば精度の高い浮動小数点数を利用するといった対処をします。どうしようもない場合もあります。
</p>
<div class="block fragment" style="border-color:lightgreen">
<h4 style="color:lightgreen">数式の変形による対処の例</h4>
<p>
例えば以下の左辺では\(h\)が小さい時に桁落ちの影響が大きくなりますが,右辺のように変形すればこれを回避出来ます。
\[ \frac{\sqrt{x+h}-\sqrt{x}}{h} = \frac{1}{\sqrt{x+h}+\sqrt{x}} \]
</p>
</div>
</section>
<section>
<h2> 情報落ち </h2>
<p>
絶対値の大きく異なる2数の加減算によって,絶対値の小さい方の情報が無視されてしまう現象です。
</p>
<pre><code class="python">>>> 100 + 1e-15
100.0
>>> 100 - 1e-15
100.0
</code></pre>
<div class="block" style="border-color:lightgreen">
<h4 style="border-color:lightgreen"> 対処 </h4>
<p>
上の様なケースで情報落ちを防ぎたいならば,精度の高い浮動小数点数を利用する他ありません。
</p>
<p>
また,絶対値の異なる多数の数を加えていく場合には絶対値の小さい数から加えたり,大小毎に分けて計算結果を持っておくなどの対処が考えられます。
</p>
</div>
</section>
<section>
<h2> 打ち切り誤差 </h2>
<p> 反復計算などを途中で打ち切る事によって生じる誤差です。解析には微積分や線型代数の知識が必要になるので,随時説明をしていきます。</p>
<div class="block fragment" style="border-color:lightgreen">
<p>
例えば,
\[ \sin x = x - \frac{x^3}{3!} + \frac{x^5}{5!} - \frac{x^7}{7!} + \cdots \]
が成り立ちます(後でやる)が,これを途中で打ち切って
\[ \sin x \approx x - \frac{x^3}{3!} + \frac{x^5}{5!} - \frac{x^7}{7!} + \cdots + (-1)^n\frac{x^{2n+1}}{(2n+1)!}\]
とすると\(n\)に応じて大小の誤差が生じます。
</p>
</div>
</section>
<section>
<p>
\(\sin\frac{\pi}{2} = 1\)を今の公式で計算してみます。
</p>
<pre><code class="python">>>> from math import pi
>>> v = 0.0
>>> x = pi/2
>>> term = x
>>> for k in range(1, 10):
... v += term
... print "{0}: {1:.16f}".format(k, v)
... term *= -x*x/((2*k)*(2*k+1))
...
1: 1.5707963267948966
2: 0.9248322292886504
3: 1.0045248555348174
4: 0.9998431013994987
5: 1.0000035425842861
6: 0.9999999437410509
7: 1.0000000006627803
8: 0.9999999999939768
9: 1.0000000000000437
</code></pre>
</section>
<section>
<h2> 二進と十進の変換 </h2>
<p>
私達が使う十進小数と,計算機が使う二進小数を相互に変換すると誤差が発生します。
</p>
<div class="block" style="border-color:lightgreen">
<h4 style="color:lightgreen">例:十進の0.1</h4>
十進の\(0.1\)は二進では無限小数となりますので誤差が生じます。例えば倍精度での\(0.1\)は
\[\frac{1}{10} + \color{pink}{\frac{1}{5\times 2^{55}}} \]
という値になり\(5.55\times 10^{-18}\)程度の誤差を含みます。
</div>
</section>
<section>
<p>
字面上では正確な小数に見えてしまう為,気をつけないと以下のようなミスをします。実際には\(0.1\)には誤差が含まれ,加算の誤差の累積も生じています。
</p>
<pre><code class="python">>>> t = 0.0
>>> while (t < 1.0): # 0.0, 0.1, 0.2, ..., 0.9と回すつもり
... print t
... t += 0.1
...
0.0
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
0.9
1.0 # t < 1.0を通過している??
</code></pre>
</section>
<section>
<p> この場合,誤差の生じない整数を利用して回すのが正解です。</p>
<pre><code class="python">>>> for i in range(10): # i = 0, 1, 2, ..., 9
... t = i*0.1
... print t
...
0.0
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
0.9
</code></pre>
</section>
<section>
<h2> 誤差の伝播 </h2>
<p>
\( f(x_1,\cdots,x_n) \)という値を計算する為に近似値\(\widetilde{x_1},\cdots,\widetilde{x_n}\)と,\(f\)を近似した関数\(\widetilde{f}\)を用いることにしましょう。
</p>
<p class="fragment">
この場合の誤差は
\[ \begin{aligned}
&f(x_1,\cdots,x_n) - \widetilde{f}(\widetilde{x_1},\cdots,\widetilde{x_n}) \\
= &\left\{f(\widetilde{x_1},\cdots,\widetilde{x_n}) - \widetilde{f}(\widetilde{x_1},\cdots,\widetilde{x_n})\right\} \\
+ & \left\{f(x_1,\cdots,x_n) - f(\widetilde{x_1},\cdots,\widetilde{x_n})\right\}
\end{aligned}
\]
となるので,近似演算が原因である第1項と,引数の誤差が原因である第2項(<strong>伝播誤差</strong>)からなります。
</p>
</section>
<section>
<h2> 伝播誤差の大きさ </h2>
<p>
伝播誤差の詳しい記述には微積分の知識が必要となりますが,直感的には下図の様に<strong>変化率の大きい所で伝播誤差も大きくなる</strong>という事が言えます
</p>
<div align="center"> <div> <img width="400px" src="fig/propagation-error.png"></div> </div>
</section>
<!--
<section>
<h2> 誤差の累積 </h2>
<p>
以上に説明した様な様々な誤差が計算を重ねる事によって累積していきます。
累積誤差の解析は非常に難しく,まだ十分にその理論が確立されていません。
</p>
</section>
<section>
<h2> 簡単な累積のモデル </h2>
<p>
非常に極端な仮定ですが,「一回の計算で必ず\(+E\)か\(-E\)の誤差(\(E\)は定数)がランダムに加算される」という場合を考えてみます。
</p>
<p>
解析には統計の知識が必要となりますので,本日の所は目で見て直感的に理解しましょう。
</p>
</section>
<section graphics="randomwalk">
<p>
誤差累積のシミュレーションです。位置\(x\)にある時,トータルの誤差が\(xE\)となります。
</p>
<svg></svg>
</section>
<section graphics="randomwalk2">
<p>
100サンプル同時に動かして見ましょう。
</p>
<svg></svg>
</section>
-->
<section>
<h2 class="chapter-title"> 極限・微分 </h2>
</section>
<section>
<h2> 「微分」では何をしたいのか? </h2>
<p>
微積分学における微分分野では,一変数関数\(f(x)\)や多変数関数\(f(x_1, x_2, \cdots, x_n)\)の<strong>連続的な変化の様子</strong>が考察の対象となります。
</p>
<p>
関数の変化の様子を記述には<strong>導関数</strong>や<strong>偏導関数</strong>を利用し,その定義の為に<strong>極限</strong>という概念が必要となります。
</p>
</section>
<section graphics="diff-sin">
<p>
<strong>導関数</strong>とは,直感的には関数\(f(x)\)のグラフ\(y=f(x)\)の各点での接線の傾き(<strong>微分係数</strong>)を与える関数であると言えます。
</p>
<svg></svg>
<p style="font-size:70%">
上図は\(y=\sin x\)とその導関数\(y=\cos x\)という例です。
</p>
</section>
<section graphics="diff-intro">
<p>
2点\((x, f(x))\)と\((x+h, f(x+h))\)を通る直線の傾きは
\[ \frac{f(x+h)-f(x)}{h} \]
となります。直感的には<strong>\(h\)を\(0\)に近づけていく</strong>と,この値が点\((x, f(x))\)での傾きに<strong>限りなく近づく</strong>という事が言えそうです。
</p>
<svg></svg>
</section>
<section>
<h2> 極限 </h2>
<p>
今考察した事を正確に述べる為に<strong>極限</strong>という概念を導入します。
</p>
<div class="block" style="border-color:pink;font-size:90%">
<h4 style="color:pink"> 数列の極限の素朴な定義 </h4>
<p>
数列\(a_1,a_2,a_3,\cdots\)の値がある定数\(\alpha\)に限りなく近づいていくならば,\(\{a_n\}\)は\(\alpha\)に収束すると言い,以下の様に表す。
\[ \lim_{n\rightarrow\infty}a_n = \alpha \]
</p>
</div>
<div class="block" style="border-color:pink;font-size:90%">
<h4 style="color:pink"> 関数の極限の素朴な定義 </h4>
<p>
\(x\)を\(a\)に近づけた時,\(f(x)\)の値がある定数\(\alpha\)に限りなく近づいていくならば,\(f(x)\)は\(x\rightarrow a\)で\(\alpha\)に収束すると言い,以下のように表す。
\[ \lim_{x\rightarrow a}f(x) = \alpha\]
</p>
</div>
</section>
<section>
<h2> 数列の極限の例 </h2>
<p>
例えば\( a_n = \frac{1}{n} \)という数列は
\[ 1, \frac{1}{2}, \frac{1}{3}, \cdots, \frac{1}{10000},\cdots \]
と限りなく\(0\)に近づいていくので
\[ \lim_{n\rightarrow\infty}\frac{1}{n} = 0\]
となります。
</p>
</section>
<section>
<h2> 関数の極限の例 </h2>
<p>
例えば\(f(x) = \frac{1}{1+x}\)という関数は\(x\rightarrow 0\)の時,限りなく\(1\)に近づいていくので
\[ \lim_{x\rightarrow 0}\frac{1}{1+x} = 1 \]
となります。
</p>
</section>
<section>
<p>
高校数学では以上の様に説明されますが,なんだか怪しいと思った人もいるのではないかと思います。
</p>
<p>
素朴な定義では<strong>限りなく近づく</strong>という事の意味が曖昧になってしまっています。
</p>
<p class="fragment">
そこで<strong>\(\varepsilon-N\)論法</strong>,<strong>\(\varepsilon-\delta\)論法</strong>と呼ばれる定義を紹介します。
</p>
</section>
<section>
<h2> 「限りなく近づいていく」とは </h2>
<p>
まず,\(a_n\)の値を\(\alpha\)に限りなく「近づける事が出来る」というのは,
<strong>どのような距離の限界\(\varepsilon > 0\)を用意してもそれより近づける</strong>ということなので,
</p>
<div class="block" style="border-color:pink">
\[ \text{任意の$\varepsilon > 0$に対して}|a_n - \alpha| < \varepsilon \text{となる$n$が存在する}\]
</div>
と定義できます。
</p>
<p class="fragment" data-fragment-index="1">
そして,限りなく「近づいていく」というのは限界\(\varepsilon\)が与えられた時に
\[ a_1,a_2,a_3,a_4,a_5\cdots, \]
の<strong>ある所から先は常に\(|a_n-\alpha|<\varepsilon\)を満たす</strong>ことだと言えます。
</p>
</section>
<section>
<h2> \(\varepsilon-N\)論法 </h2>
<div class="block" style="border-color:pink">
<h4 style="color:pink">\(\varepsilon-N\)論法による数列の極限の定義</h4>
<p>
任意の\(\varepsilon > 0\)に対してある自然数\(N\)が存在して,
\[ n > N\ \text{ならば}\ |a_n - \alpha| < \varepsilon\]
となる時\(\{a_n\}\)は\(\alpha\)に収束すると言い,下のように表す
\[ \lim_{n\rightarrow\infty}a_n = \alpha \]
</p>
</div>
</section>
<section>
<p>
\(\displaystyle\lim_{n\rightarrow\infty}\frac{1}{n} = 0\)を\(\varepsilon-N\)論法で証明してみます。
</p>
<p>[証明]<br>
任意の\(\varepsilon > 0\)に対して自然数\(N\)を
\[ N > \frac{1}{\varepsilon} \]
を満たすようにとれば\(n > N\)の時
\[ \left|\frac{1}{n}-0\right| = \frac{1}{n} < \frac{1}{N} < \varepsilon \]
を満たす。従って
\[ \lim_{n\rightarrow\infty}\frac{1}{n} = 0 \]
である。<span style="float:right">□</span> </p>
</p>
</section>
<section>
<h2> \(\varepsilon-\delta\)論法 </h2>
<p> 同様にして関数の極限も定義されます。 </p>
<div class="block" style="border-color:pink">
<h4 style="color:pink">\(\varepsilon-\delta\)論法による関数の極限の定義</h4>
<p>
任意の\(\varepsilon > 0\)に対してある\(\delta > 0\)が存在して,
\[ 0 < |x-a| < \delta\ \text{ならば}\ |f(x)-\alpha|<\varepsilon\]
となる時\(f(x)\)は\(x\rightarrow a\)で\(\alpha\)に収束すると言い,下のように表す
\[ \lim_{x\rightarrow a}f(x) = \alpha \]
</p>
</div>
</section>
<section>
<h2>練習問題</h2>
<p>
\(\varepsilon-\delta\)論法で\(\displaystyle\lim_{x\rightarrow 0}\frac{1}{1+x} = 1\)を証明して下さい。
</p>
</section>
<section>
<h2> 微分係数 </h2>
<p>
以上の準備によって<strong>微分係数</strong>を定義する事が出来ます。
</p>
<div class="block" style="border-color:pink;font-size:90%">
<h4 style="color:pink">微分係数</h4>
<p>
関数\(f(x)\)に対して極限
\[ \lim_{h\rightarrow 0}\frac{f(a+h)-f(a)}{h} \]
が収束する時,この値を\(x=a\)における\(f(x)\)の<strong>微分係数</strong>と言い
\[ f'(a),\ \frac{\mathrm{d}f}{\mathrm{d}x}(a),\ \left.\frac{\mathrm{d}}{\mathrm{d}x}f(x)\right|_{x=a} \]
などと表す。
</p>
</div>
<p>
\(f'(a)\)が存在する時,\(f(x)\)は\(x=a\)で<strong>微分可能</strong>であると言います。
</p>
</section>
<section>
<h2> 導関数 </h2>
<div class="block" style="border-color:pink;font-size:90%">
<h4 style="color:pink">導関数</h4>
<p>
微分係数\(f'(a)\)は\(x=a\)を変化させる事により\(x\)の関数,
\[ f'(x) = \lim_{h\rightarrow 0}\frac{f(x+h)-f(x)}{h} \]
となる。これを\(y=f(x)\)の<strong>導関数</strong>と言い,
\[ f'(x),\ y',\ \frac{\mathrm{d}}{\mathrm{d}x}f(x),\ \frac{\mathrm{d}y}{\mathrm{d}x}\]
などと表す。
</p>
</div>
<p>
先ほど説明したように,\(f'(x)\)は\(y=f(x)\)の各点での傾きと解釈する事ができます。
</p>
</section>
<section>
<h2> 導関数の例 </h2>
<p>
\(f(x) = x^2\)の導関数を計算してみると,
</p>
<p>
\[\begin{aligned}
f'(x) &= \lim_{h\rightarrow 0}\frac{f(x+h)-f(x)}{h}= \lim_{h\rightarrow 0}\frac{(x+h)^2-x^2}{h}\\
&= \lim_{h\rightarrow 0}\frac{2xh+h^2}{h}= \lim_{h\rightarrow 0}(2x+h)\\
&= 2x
\end{aligned} \]
となります。
</p>
<p>
【練習問題】\(\left(\frac{1}{x}\right)' = -\frac{1}{x^2}\)を示して下さい。
</p>
</section>
<section>
<h2> 基本的な関数の導関数 </h2>
<p>
以下,よく使う基本的な関数の導関数を紹介します。
</p>
<p>
導出は省略するので教科書を参照してください。
</p>
</section>
<section graphics="diff-poly">
<div class="block" style="border-color:pink;font-size:90%">
\[ (x^\alpha)' = \alpha x^{\alpha-1}\qquad(\text{$\alpha$は任意の実数})\]
</div>
<svg></svg>
<p style="font-size:80%"> グラフは\((x^2)'=2x\)の例 </p>
</section>
<section graphics="diff-sin">
<div class="block" style="border-color:pink;font-size:90%">
\[ (\sin x)' = \cos x \]
</div>
<svg></svg>
</section>
<section graphics="diff-cos">
<div class="block" style="border-color:pink;font-size:90%">
\[ (\cos x)' = -\sin x \]
</div>
<svg></svg>
</section>
<section>
<h2> その他三角関数の導関数 </h2>
<div class="block" style="border-color:pink;font-size:90%">
\[ \begin{aligned}
(\tan x)' &= \frac{1}{\cos^2 x} \\
\left(\frac{1}{\tan x}\right)' &= -\frac{1}{\sin^2 x} \\
(\sin^{-1} x)' &= \frac{1}{\sqrt{1-x^2}} \\
(\cos^{-1} x)' &= -\frac{1}{\sqrt{1-x^2}} \\
(\tan^{-1} x)' &= \frac{1}{1+x^2}
\end{aligned} \]
</div>
</section>
<section>
<h2> 自然対数の底 </h2>
<div class="block" style="border-color:pink;font-size:90%">
<h4 style="color:pink">自然対数の底</h4>
\[ e = \lim_{n\rightarrow\infty}\left(1+\frac{1}{n}\right)^n \]
という極限値として定義される\(e\)を<strong>自然対数の底</strong>,もしくは<strong>ネイピア数</strong>と言う。その値は無理数であり
\[ e = 2.718281828459045\cdots \]
となる。
</div>
<p style="font-size:80%">
\(\left(1+\frac{1}{n}\right)^n\)が収束する事,\(e\)が無理数である事の証明は教科書を参照して下さい。
</p>
</section>
<section>
<h2> 指数関数・対数関数 </h2>
<p>
ネイピア数\(e\)を底とする指数関数,対数関数は重要なので以下の記法がよく使われます。
</p>
<div class="block" style="border-color:pink;font-size:90%">
<h4 style="color:pink">指数・対数関数</h4>
<p>
ネイピア数\(e\)を底とする指数関数,対数関数を以下の様に表す。
\[ \begin{aligned}
\color{pink}{\exp x} &= e^x\\
\color{pink}{\ln x} &= \log_e x
\end{aligned} \]
</p>
</div>
</section>
<section graphics="diff-exp">
<div class="block" style="border-color:pink;font-size:90%">
\[ (\exp x)' = \exp x \]
</div>
<svg></svg>
</section>
<section graphics="diff-ln">
<div class="block" style="border-color:pink;font-size:90%">
\[ (\ln x)' = \frac{1}{x} \]
</div>
<svg></svg>
</section>
<section>
<h2> 微分の公式 </h2>
<p>
導関数の定義より以下の公式を示す事が出来ます。
</p>
<div class="block" style="border-color:pink;font-size:90%">
\[ \begin{aligned}
\{kf(x)\}' &= kf'(x)\qquad(\text{$k$は定数})\\
\{f(x)\pm g(x)\}' &= f'(x) \pm g'(x) \\
\{f(x)g(x)\}' &= f'(x)g(x) + f(x)g'(x) \\
\left\{\frac{f(x)}{g(x)}\right\}' &= \frac{f'(x)g(x)-f(x)g'(x)}{\{g(x)\}^2} \\
\{f(g(x))\}' &= f'(g(x))g'(x) \qquad\text{(合成関数の微分法)}
\end{aligned} \]
</div>
</section>
<section>
<h2> 公式を利用した計算の例 </h2>
<p>
\(f(x) = \exp\left(-\frac{x^2}{2}\right)\)の導関数を求めてみます。
</p>
<p>
合成関数の微分法により