Skip to content

Commit

Permalink
Merge pull request #183 from chvmvd/update-week12-13-article
Browse files Browse the repository at this point in the history
Update week12 13 article
  • Loading branch information
chvmvd authored Jan 15, 2023
2 parents 8867a63 + 6bfa8d6 commit 3cbac04
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 62 deletions.
18 changes: 11 additions & 7 deletions docs/02algorithms/09error/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@ $12345 = \underbrace{1.2345}_{\text{仮数部}}\times 10^{\overbrace{-4}^{\text{

まずは、10 進数で考えましょう。
例えば、$\frac{1}{3}$ は有限桁の小数では表せません。$0.3$ も $0.33$ も $0.333$ も $\frac{1}{3}$ の近似でしかありません。
たとえ、 $0.3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333$ のようにしても同じことです。
たとえ、次のようにどんなに桁を大きくしても有限である限り近似には変わりません。

$$
0.3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333
$$

2 進数においても同じことが起こります。
10 進数の $0.1$ を 2 進数で表すことを考えます。
Expand All @@ -37,11 +41,11 @@ $$

このように $0.1_{(10)}$ は 2 進数では有限桁で表せません。

コンピューターは、有限桁しか表現できないことから、有効桁以降を切り捨てます。これによって、誤差が出るのが丸め誤差です。
無限桁を扱うことはできないので、有効桁以降を切り捨てることになります。これによって、誤差が出るのが丸め誤差です。

## 桁落ち

有効数字を 7 桁で $\sqrt{1001}-\sqrt{999}$ を計算することを考えます。
有効数字 7 桁で $\sqrt{1001}-\sqrt{999}$ を計算することを考えます。

$$
\sqrt{1001} = 31.638584\dots \simeq 31.63858
Expand All @@ -57,11 +61,11 @@ $$
\sqrt{1001}-\sqrt{999} \simeq 0.03162
$$

このようにすると、有効数字が 4 桁になってしまいます
このようにすると、有効数字が 4 桁に減ってしまいます

このように値がほぼ同じ数値同士で減算をしたときに有効桁数が減少することによって生まれる誤差が桁落ちです。

今回の場合は、回避策があります。
実は今回の場合は、回避策があります。

$$
\begin{align*}
Expand All @@ -74,7 +78,7 @@ $$
\end{align*}
$$

これで、桁落ちを回避できます
今回の場合ならば、これで桁落ちを回避できます

## 情報落ち

Expand All @@ -98,7 +102,7 @@ $$

となって正しく計算できません。

次のように、何度も足す場合には計算結果が変わってきてしまいます
次のように、何度も足す場合には深刻になってきます

$$
\begin{align*}
Expand Down
38 changes: 19 additions & 19 deletions docs/02algorithms/10gaussian-elimination/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,11 @@ $$

## Gauss の消去法

Gauss の消去法を使えば、システマティックに連立一次方程式を解くことができます。掃き出し法とも呼ばれます。
線形代数で習う Gauss の消去法を使えば、システマティックに連立一次方程式を解くことができます。そのため、このアルゴリズムを用いれば連立方程式を解くプログラムを簡単に作ることができます。Gauss の消去法は、掃き出し法とも呼ばれます。

Gauss の消去法は、前進消去と後退代入の二段階から成ります。

簡単に Gauss の消去法を説明しておきます。
先に線形代数の復習として、簡単に Gauss の消去法を説明しておきます。

次のように $n$ 個の未知数 $x_1, x_2, x_3, \dots , x_n$ に対して、$m$ 個の方程式を考えます。

Expand Down Expand Up @@ -206,10 +206,10 @@ $$
\right.
$$

これで $x_n$ から順番に求めていくことで連立方程式を解くことができます
これで $x_n$ はすぐに求めることができます。さらに、$x_n$ の解を代入すれば、$x_{n-1}$ もすぐに求まります。これを繰り返していくことで、連立方程式を解くことができます

実際に連立方程式を解いてみましょう
Gauss の消去法を次の方程式系について行うと、以下のようになります
実際に具体的な連立方程式を解いてみましょう
Gauss の消去法を次の方程式系について行ってみます

$$
\left\{
Expand All @@ -221,7 +221,7 @@ $$
\right.
$$

まずは、前進消去を行います。
まずは、前進消去を行います。基本変形を繰り返して、行階段行列を作っていきます。

$$
\begin{alignat*}{2}
Expand Down Expand Up @@ -305,15 +305,14 @@ $$
\right.
$$

Gauss の消去法を使えば、このようにシステマティックに連立方程式を解けます。
これなら、プログラムを作るのは簡単そうです。

:::info

次のように、前進消去の段階で行簡約行列を作れば、後退代入を行う必要がなくなります。これは、Gauss-Jordan の消去法と呼ばれます。
しかし、実は先程のように行簡約行列まで計算しないで途中で止める Gauss の消去法の方が計算量が少なくなるので、Gauss の消去法を使って説明をしました。
Gauss-Jordan の消去法の方が良さそうですが、実は先程のように行簡約行列まで計算しないで途中で止める Gauss の消去法の方が計算量が少し少なくなります。そのため、Gauss の消去法の方がよく使われます。

Gauss-Jordan の消去法で先程の連立方程式を解いてみます。

行簡約行列は次のようになります
拡大係数行列に基本変形を繰り返すと、次のような行簡約行列が得られます

$$
\tilde{B} =
Expand Down Expand Up @@ -350,8 +349,8 @@ $$

これで連立方程式を解くことができました。

実際に連立方程式を解いてみます
これを次の方程式系について行うと、以下のようになります
実際に具体的な連立方程式を解いてみます
Gauss-Jordan の消去法を次の方程式系について行っていきます

$$
\left\{
Expand Down Expand Up @@ -464,7 +463,7 @@ $i$ 行、$i$ 列が pivot となるので、$i$ 行目を pivot の値で割っ

次は、後退代入を行います。

$x_n$ $d_n$ になります。求まった $x_n$ をそれよりも上の式に代入して、$b_{j, n}x_n(1\leq j\leq n-1)$ を右辺に移動させ、$d_j(1\leq j\leq n-1)$ の値を更新します。これを繰り返すと、後退代入ができます
$x_n = d_n$ になります。求まった $x_n$ をそれよりも上の式すべてに代入して、$b_{j, n}x_n(1\leq j\leq n-1)$ を右辺に移動させ、$d_j(1\leq j\leq n-1)$ の値を更新します。こうすると、$x_{n-1}$ が求まります。これを繰り返すと連立一次方程式が解けます

プログラムは次のようになります。計算量は、$O(n^3)$ です。

Expand All @@ -474,7 +473,8 @@ $x_n$ は $d_n$ になります。求まった $x_n$ をそれよりも上の式

## 部分ピボット選択

次のような連立方程式を解こうとすると、次のようなエラーが出てしまいます。
さきほどのプログラムを使えば、多くの様々な連立一次方程式が解けます。
しかし、次の連立方程式を解くと、次のようにエラーが出てしまいます。

$$
\left\{
Expand All @@ -488,12 +488,12 @@ $$

<ViewSource path="/gaussian-elimination/gaussian_elimination_error.ipynb" />

これは、前進消去の際に 0 で割る操作ができてしまったためです
これを解決するために、部分ピボット選択を行います。誤差を小さくする役割もあります。
これは、前進消去の際に 0 で割る操作が起こってしまったからです
これを解決するために、部分ピボット選択を行います。部分ピボット選択には、誤差を小さくする役割もあります。

部分ピボット選択は、pivot 列の pivot 行以降の行で絶対値が最大になる行を pivot に使うように変形することです。

先程の連立方程式なら、次のようになります
先程の連立方程式なら、次のように計算していきます。1 つ目から、2 つ目への変形が部分ピボット選択によるものです

$$
\begin{alignat*}{2}
Expand Down Expand Up @@ -556,7 +556,7 @@ $$
\end{alignat*}
$$

部分ピボット選択を使うと、次のようになります
部分ピボット選択を入れると、次のようなプログラムになります

<ViewSource path="/gaussian-elimination/gaussian_elimination_revised.ipynb" />

Expand Down
Loading

0 comments on commit 3cbac04

Please sign in to comment.