From 9a7442acbef96ea8d5b435a7409c47d40312ea4a Mon Sep 17 00:00:00 2001
From: chvmvd <chvmvd@users.noreply.github.com>
Date: Tue, 17 Jan 2023 15:20:35 +0900
Subject: [PATCH] Add description in error article

---
 docs/02algorithms/09error/index.mdx     | 51 ++++++++++++++++++++++++-
 static/error/cancellation.ipynb         | 36 +++++++++++++++++
 static/error/cancellation_correct.ipynb | 33 ++++++++++++++++
 static/error/loss.ipynb                 | 28 ++++++++++++++
 static/error/loss_correct.ipynb         | 28 ++++++++++++++
 static/error/rounding_error.ipynb       | 27 +++++++++++++
 6 files changed, 202 insertions(+), 1 deletion(-)
 create mode 100644 static/error/cancellation.ipynb
 create mode 100644 static/error/cancellation_correct.ipynb
 create mode 100644 static/error/loss.ipynb
 create mode 100644 static/error/loss_correct.ipynb
 create mode 100644 static/error/rounding_error.ipynb

diff --git a/docs/02algorithms/09error/index.mdx b/docs/02algorithms/09error/index.mdx
index 240316998..2062cca7c 100644
--- a/docs/02algorithms/09error/index.mdx
+++ b/docs/02algorithms/09error/index.mdx
@@ -17,6 +17,8 @@ $12345 = \underbrace{1.2345}_{\text{仮数部}}\times 10^{\overbrace{-4}^{\text{
 
 ## 丸め誤差
 
+### 丸め誤差とは
+
 世の中には、有限桁の小数では表せない数字は多くあります。
 
 まずは、10 進数で考えましょう。
@@ -41,10 +43,18 @@ $$
 
 このように $0.1_{(10)}$ は 2 進数では有限桁で表せません。
 
-無限桁を扱うことはできないので、有効桁以降を切り捨てることになります。これによって、誤差が出るのが丸め誤差です。
+コンピューターは二進数で処理をするので一度二進数に変換しますが、そのときに無限桁を扱うことはできないので、有効桁以降を切り捨てることになります。これによって、誤差が出るのが丸め誤差です。
+
+### 丸め誤差の例
+
+さきほど述べたように $0.1_{(10)}$ を二進数で表すと丸め誤差が発生します。そのため、例えば $0.1\times 3$ を計算すると丸め誤差の影響が現れます。
+
+<ViewSource path="/error/rounding_error.ipynb" />
 
 ## 桁落ち
 
+### 桁落ちとは
+
 有効数字 7 桁で $\sqrt{1001}-\sqrt{999}$ を計算することを考えます。
 
 $$
@@ -65,6 +75,8 @@ $$
 
 このように値がほぼ同じ数値同士で減算をしたときに有効桁数が減少することによって生まれる誤差が桁落ちです。
 
+### 回避策
+
 実は今回の場合は、回避策があります。
 
 $$
@@ -80,8 +92,20 @@ $$
 
 今回の場合ならば、これで桁落ちを回避できます。
 
+### 桁落ちの例
+
+少し桁を大きくして、実際に確かめてみましょう。
+
+上が桁落ちが起こってしまった例で、下が桁落ちを回避した例です。確かに、上はずれてしまいましたね。
+
+<ViewSource path="/error/cancellation.ipynb" />
+
+<ViewSource path="/error/cancellation_correct.ipynb" />
+
 ## 情報落ち
 
+### 情報落ちとは
+
 次の場合、有効数字が 5 桁なら
 
 $$
@@ -115,4 +139,29 @@ $$
 
 このように、絶対値の大きい数と絶対値の小さい数を加減算したときに、絶対値の小さな数字が無視されてしまうことを情報落ちといいます。
 
+### 回避策
+
+これには、回避策があります。
+
+小さい数を先に足して、その後に大きい数を足せば回避できます。
+
+$$
+\begin{align*}
+    4.000 + 4.000 + 4.000 + 1.000\times 10^4 &= 8.000 + 4.000 + 1.000 \times 10^4 \\
+                                             &= 12.000 + 1.000 \times 10^4 \\
+                                             &= 1.0012 \times 10^4 \\
+                                             &\simeq 1.001 \times 10^4 \\
+\end{align*}
+$$
+
+これで、有効数字 4 桁で正しい計算ができました。
+
+### 情報落ちの例
+
+10000000000 に 0.0000001 を 10000000 回足すと、10000000001 になります。しかし、上の計算では正しく計算できていません。一方、下の計算では正しく計算できます。
+
+<ViewSource path="/error/loss.ipynb" />
+
+<ViewSource path="/error/loss_error.ipynb" />
+
 <!-- ## 打ち切り誤差 -->
diff --git a/static/error/cancellation.ipynb b/static/error/cancellation.ipynb
new file mode 100644
index 000000000..e04578133
--- /dev/null
+++ b/static/error/cancellation.ipynb
@@ -0,0 +1,36 @@
+{
+ "nbformat": 4,
+ "nbformat_minor": 2,
+ "metadata": {},
+ "cells": [
+  {
+   "metadata": {},
+   "source": [
+    "import math"
+   ],
+   "cell_type": "code",
+   "outputs": [],
+   "execution_count": null
+  },
+  {
+   "metadata": {},
+   "source": [
+    "math.sqrt(100001) - math.sqrt(99999)"
+   ],
+   "cell_type": "code",
+   "outputs": [
+    {
+     "output_type": "execute_result",
+     "data": {
+      "text/plain": [
+       "0.003162277660237578"
+      ]
+     },
+     "metadata": {},
+     "execution_count": 13
+    }
+   ],
+   "execution_count": null
+  }
+ ]
+}
diff --git a/static/error/cancellation_correct.ipynb b/static/error/cancellation_correct.ipynb
new file mode 100644
index 000000000..fd44867d9
--- /dev/null
+++ b/static/error/cancellation_correct.ipynb
@@ -0,0 +1,33 @@
+{
+ "nbformat": 4,
+ "nbformat_minor": 2,
+ "metadata": {},
+ "cells": [
+  {
+   "metadata": {},
+   "source": [
+    "import math"
+   ],
+   "cell_type": "code",
+   "outputs": [],
+   "execution_count": null
+  },
+  {
+   "metadata": {},
+   "source": [
+    "print(2 / (math.sqrt(100001) + math.sqrt(99999)))"
+   ],
+   "cell_type": "code",
+   "outputs": [
+    {
+     "output_type": "stream",
+     "name": "stdout",
+     "text": [
+      "0.0031622776602079072\n"
+     ]
+    }
+   ],
+   "execution_count": null
+  }
+ ]
+}
diff --git a/static/error/loss.ipynb b/static/error/loss.ipynb
new file mode 100644
index 000000000..5b1d658e6
--- /dev/null
+++ b/static/error/loss.ipynb
@@ -0,0 +1,28 @@
+{
+ "nbformat": 4,
+ "nbformat_minor": 2,
+ "metadata": {},
+ "cells": [
+  {
+   "metadata": {},
+   "source": [
+    "r = 0\n",
+    "r += 10000000000\n",
+    "for i in range(10000000):\n",
+    "    r += 0.0000001\n",
+    "print(r)"
+   ],
+   "cell_type": "code",
+   "outputs": [
+    {
+     "output_type": "stream",
+     "name": "stdout",
+     "text": [
+      "10000000000.0\n"
+     ]
+    }
+   ],
+   "execution_count": null
+  }
+ ]
+}
diff --git a/static/error/loss_correct.ipynb b/static/error/loss_correct.ipynb
new file mode 100644
index 000000000..ebbb44e91
--- /dev/null
+++ b/static/error/loss_correct.ipynb
@@ -0,0 +1,28 @@
+{
+ "nbformat": 4,
+ "nbformat_minor": 2,
+ "metadata": {},
+ "cells": [
+  {
+   "metadata": {},
+   "source": [
+    "r = 0\n",
+    "for i in range(10000000):\n",
+    "    r += 0.0000001\n",
+    "r += 10000000000\n",
+    "print(r)"
+   ],
+   "cell_type": "code",
+   "outputs": [
+    {
+     "output_type": "stream",
+     "name": "stdout",
+     "text": [
+      "10000000001.0\n"
+     ]
+    }
+   ],
+   "execution_count": null
+  }
+ ]
+}
diff --git a/static/error/rounding_error.ipynb b/static/error/rounding_error.ipynb
new file mode 100644
index 000000000..8ee51ce49
--- /dev/null
+++ b/static/error/rounding_error.ipynb
@@ -0,0 +1,27 @@
+{
+ "nbformat": 4,
+ "nbformat_minor": 2,
+ "metadata": {},
+ "cells": [
+  {
+   "metadata": {},
+   "source": [
+    "0.1 * 3"
+   ],
+   "cell_type": "code",
+   "outputs": [
+    {
+     "output_type": "execute_result",
+     "data": {
+      "text/plain": [
+       "0.30000000000000004"
+      ]
+     },
+     "metadata": {},
+     "execution_count": 9
+    }
+   ],
+   "execution_count": null
+  }
+ ]
+}
