ブログ

2.7.4 幾何分布 〜統計検定2級対応・統計学入門まとめ〜

当まとめでは統計検定$2$級の公式テキストの副教材に用いることができるように、統計学入門に関して取り扱います。当記事では「統計検定$2$級対応 統計学基礎」の$2.7.4$節「幾何分布」の内容を元に幾何分布の確率関数や期待値・分散の計算に関して取りまとめました。
統計検定$2$級のテキストとの対応がわかりやすいように、目次を「統計検定$2$級対応 統計学基礎」と対応させました。学びやすさの観点からあえて目次を対応させましたが、当まとめは「統計の森」オリジナルのコンテンツであり、統計検定の公式とは一切関係ないことにご注意ください。

・統計検定$2$級対応・統計学入門まとめ
https://www.hello-statisticians.com/stat_basic

幾何分布の概要

概要

確率$p$の事象が$x$回目に初めて観測される確率を取り扱う場合、幾何分布を用います。下記は準$1$級で出題された問題の解答ですが、$4$種類あるカードを全て入手する際に必要な試行の期待値について取り扱われており、幾何分布の応用例と見ることができます。

発展事項

幾何分布では確率$p$の事象が$1$回目観測される時点に関して取り扱いますが、$r$回目の観測の時点を取り扱う場合は「負の二項分布」を用います。負の二項分布に関しては下記で詳しく取り扱いましたので、確認の際は下記をご参照ください。

必要な数学

幾何分布の確率関数には指数関数が用いられます。よって、指数関数の理解は必須になります。

幾何分布の確率関数・期待値・分散

幾何分布の確率関数

$x$回目で$1$度目に確率$p$の事象が観測されたと考えるとき、確率変数$X$は幾何分布$\mathrm{Geo}(p)$に従うと考えられます。幾何分布の確率関数を$p(x)$とおくと、$p(x)$は下記のように表すことができます。
$$
\large
\begin{align}
p(x) = p(1-p)^{x-1}, \quad x=1,2,3,\cdots
\end{align}
$$

注意事項

幾何分布を考えるにあたっては「$x$回目に確率$p$の事象が観測される」のように定義する場合と、「$x$回の失敗ののちに成功する」のように定義する場合の$2$通りあります。ここでは前者を用いましたが、後者が用いられる場合もあるので、確率関数に着目する必要があります。

$(1-p)^{x-1}$が用いられる場合は「$x$回目に確率$p$の事象が観測される」と考える、$(1-p)^{x}$が用いられた場合は「$x$回の失敗ののちに成功する」と考えることは抑えておくと良いと思います。

幾何分布の期待値・分散

幾何分布の期待値$E[X]$と分散$V[X]$は下記に基づいて計算することができます。
$$
\large
\begin{align}
E[X] &= \frac{1}{p} \\
V[X] &= \frac{1-p}{p^2}
\end{align}
$$

導出はやや複雑なので当項では省略します。詳しくは下記などで取り扱いました。

2.7.3 ポアソン分布 〜統計検定2級対応・統計学入門まとめ〜

当まとめでは統計検定$2$級の公式テキストの副教材に用いることができるように、統計学入門に関して取り扱います。当記事では「統計検定$2$級対応 統計学基礎」の$2.7.3$節「ポアソン分布」の内容を元にポアソン分布の確率関数や期待値・分散の計算に関して取りまとめました。
統計検定$2$級のテキストとの対応がわかりやすいように、目次を「統計検定$2$級対応 統計学基礎」と対応させました。学びやすさの観点からあえて目次を対応させましたが、当まとめは「統計の森」オリジナルのコンテンツであり、統計検定の公式とは一切関係ないことにご注意ください。

・統計検定$2$級対応・統計学入門まとめ
https://www.hello-statisticians.com/stat_basic

ポアソン分布の概要

概要

ポアソン分布は二項分布$\mathrm{Bin}(n,p)$の$np = \lambda$を固定し、$n \to \infty, p \to 0$の極限を考えた際の確率分布です。

よってポアソン分布は「稀に起きる現象」の近似の際によく用いられます。具体的には「交通事故の件数」や「工場で発生する不良品の件数」などが例に挙げられます。確率関数や確率関数に基づく考察に関しては次節で詳しく取り扱います。

必要な数学

ポアソン分布の確率関数には指数関数やネイピア数$e$が用いられます。よって、指数関数の理解は必須になります。

また、二項分布からポアソン分布の確率関数の導出を行うにあたっては極限の考え方を用います。極限の考え方は統計検定$2$級では出題されないと思われますが、重要事項なので余裕があれば確認しておくと良いと思います。

ポアソン分布の確率関数・期待値・分散

ポアソン分布の確率関数

ポアソン分布の確率関数を$p(x)$とおくと、$p(x)$は下記のように表せる。
$$
\large
\begin{align}
p(x) = \frac{\lambda^{x} e^{-x}}{x!}
\end{align}
$$

たとえば$\lambda=2$のときは$x=0$〜$5$に対応する確率関数$p(x)$が下記のように得られます。
$$
\large
\begin{align}
p(0) &= \frac{e^{-2} \cdot 2^0}{0!} \\
&= e^{-2} \\
&= 0.1353095 \\
p(1) &= \frac{e^{-2} \cdot 2^1}{1!} \\
&= 2 \cdot e^{-2} \\
&= 0.2706709 \\
p(2) &= \frac{e^{-2} \cdot 2^2}{2!} \\
&= 2 \cdot e^{-2} \\
&= 0.2706709 \\
p(3) &= \frac{e^{-2} \cdot 2^3}{3!} \\
&= \frac{4 \cdot e^{-2}}{3} \\
&= 0.180447 \\
p(4) &= \frac{e^{-2} \cdot 2^4}{4!} \\
&= \frac{2 \cdot e^{-2}}{3} \\
&= 0.0902235 \\
p(5) &= \frac{e^{-2} \cdot 2^5}{5!} \\
&= \frac{4 \cdot e^{-2}}{15} \\
&= 0.0360894
\end{align}
$$

上記では$x=0,1,2$の確率の和が$0.6$ほどあるので、$\lambda=2$に近い値が観測されやすいことが確認できます。

発展事項

ポアソン分布の確率関数を表した$(1)$式は二項分布の確率関数より導出を行うことができます。詳しい導出の流れは下記で取り扱いましたのでここでは省略します。

ポアソン分布の期待値・分散

ポアソン分布の期待値$E[X]$や分散$V[X]$は二項分布の値に対して$\lambda = np$とした上で、$n \to \infty$、$p \to 0$の極限を考えることで導出することができます。
・期待値
$$
\large
\begin{align}
E[X] &= np \\
&= \lambda
\end{align}
$$

・分散
$$
\large
\begin{align}
V[X] &= np(1-p) \\
&= \lambda(1-p) \\
& \to \lambda \quad (1-p \to 1)
\end{align}
$$

2.7.2 二項分布 〜統計検定2級対応・統計学入門まとめ〜

当まとめでは統計検定$2$級の公式テキストの副教材に用いることができるように、統計学入門に関して取り扱います。当記事では「統計検定$2$級対応 統計学基礎」の$2.7.2$節「二項分布」の内容を元に二項分布の確率関数や期待値・分散の計算に関して取りまとめました。
統計検定$2$級のテキストとの対応がわかりやすいように、目次を「統計検定$2$級対応 統計学基礎」と対応させました。学びやすさの観点からあえて目次を対応させましたが、当まとめは「統計の森」オリジナルのコンテンツであり、統計検定の公式とは一切関係ないことにご注意ください。

・統計検定$2$級対応・統計学入門まとめ
https://www.hello-statisticians.com/stat_basic

二項分布の概要

概要

二項分布は$X_i=1$の確率が$p$であるベルヌーイ分布に基づくベルヌーイ試行を$n$回行った際に$1$が観測される回数の確率を取り扱います。たとえば確率$p=0.3$で成功する試行を$3$回行った際に$2$度成功する確率$P(X=2|n=3,p=0.3)$は下記のように表すことができます。
$$
\large
\begin{align}
P(X=2|n=3,p=0.3) &= 3 \times 0.3^{2} \times (1-0.3)^{1} \\
&= 0.189
\end{align}
$$

上記では$2$回成功、$1$回失敗を$0.3^{2} \times (1-0.3)^{1}$で表しており、成功が$1$回目・$2$回目・$3$回目のどこで起こるかの$3$通りがあることから$3$を掛けました。一般的な二項分布の確率関数の表記に関しては次節で取り扱います。

必要な数学

ベルヌーイ分布を元に二項分布の期待値や分散の式を表すにあたっては、$\displaystyle \sum$を用いることでシンプルに取り扱えるので抑えておくと良いと思います。

二項分布の確率関数・期待値・分散

二項分布の確率関数

ベルヌーイ分布の確率関数を$p(x)$とおくと、$p(x)$は下記のように表されます。
$$
\large
\begin{align}
p(x) = {}_{n} C_{x} p^{x} (1-p)^{n-x}
\end{align}
$$

式の解釈にあたっては前節で取り扱ったように$x$回成功、$n-x$回失敗を$p^{x} (1-p)^{n-x}$で表し、成功と失敗をどの順序で並べるかを${}_{n} C_{x}$を用いて表したと考えると良いです。

${}_{n} C_{x}$の解釈、緑が成功の場合、場所の組み合わせに帰着する

${}_{n} C_{x}$の理解にあたっては上図を元に考えると良いと思います。

二項分布の期待値・分散

二項分布の期待値と分散はベルヌーイ分布を元に計算を行うと良いです。$i$番目のベルヌーイ試行における確率変数を$X_i=1 \mathrm{or} 0$で表すとき、二項分布の確率変数$X$は下記のように定義することができます。
$$
\large
\begin{align}
X = \sum_{i=1}^{n} X_i
\end{align}
$$

ベルヌーイ分布」より、$E[X_i]=p, V[X_i]=p(1-p)$なので、二項分布の期待値$E[X]$と分散$V[X]$はそれぞれ下記のように考えることができます。
$$
\large
\begin{align}
E[X] &= E \left[ \sum_{i=1}^{n} X_i \right] \\
&= \sum_{i=1}^{n} E[X_i] \\
&= np \\
V[X] &= V \left[ \sum_{i=1}^{n} X_i \right] \\
&= \sum_{i=1}^{n} V[X_i] \\
&= np(1-p)
\end{align}
$$

発展事項

確率変数$X_i$が$0,1$の$2$値を取ることを上記では$X_i=1 \mathrm{or} 0$のように表しましたが、集合の表記を用いて$X_i \in \{ 0,1 \}$と表す場合が多いので抑えておくと良いです。

また、$V[X]$の計算にあたって、$V[X_1+X_2]=V[X_1]+V[X_2]$を用いましたが、$X_1$と$X_2$の相関・共分散が$0$でないとこの式は使えないことに注意が必要です。超幾何分布などが$V[X_1+X_2] \neq V[X_1]+V[X_2]$の例に挙げられますが、下記で詳しく取り扱ったので当項では省略します。

2.7.1 ベルヌーイ分布 〜統計検定2級対応・統計学入門まとめ〜

当まとめでは統計検定$2$級の公式テキストの副教材に用いることができるように、統計学入門に関して取り扱います。当記事では「統計検定$2$級対応 統計学基礎」の$2.7.1$節「ベルヌーイ分布」の内容を元にベルヌーイ分布の確率関数や期待値・分散の計算に関して取りまとめました。
統計検定$2$級のテキストとの対応がわかりやすいように、目次を「統計検定$2$級対応 統計学基礎」と対応させました。学びやすさの観点からあえて目次を対応させましたが、当まとめは「統計の森」オリジナルのコンテンツであり、統計検定の公式とは一切関係ないことにご注意ください。

・統計検定$2$級対応・統計学入門まとめ
https://www.hello-statisticians.com/stat_basic

ベルヌーイ分布の概要

概要

ベルヌーイはコイン投げのように$2$通りの結果が観測される場合を取り扱う確率分布です。たとえばコイン投げでは「表」と「裏」の$2$通りの事象が観測されます。

必要な数学

ベルヌーイ分布の期待値や分散の式を表すにあたって、$\displaystyle \sum$は必ずしも必須ではありませんが抑えておくことでシンプルに取り扱えるので抑えておくと良いと思います。

ベルヌーイ分布の確率関数・期待値・分散

ベルヌーイ分布の確率関数

ベルヌーイ分布の確率関数を$p(x)$とおくと、$p(x)$は下記のように表されます。
$$
\large
\begin{align}
p(x) = p^{x} (1-p)^{1-x}
\end{align}
$$

上記の式の理解はやや難しいですが、ベルヌーイ分布では$x$の値が$x=0,1$の$2$値であることに基づいて下記のように考えることでわかりやすいです。
・$x=1$の場合
$$
\large
\begin{align}
p(1) &= p^{1} (1-p)^{1-1} \\
&= p
\end{align}
$$

・$x=0$の場合
$$
\large
\begin{align}
p(0) &= p^{0} (1-p)^{1-0} \\
&= 1-p
\end{align}
$$

確率関数$p(x)$は「確率変数が$X=x$である確率」を表す関数であるので、$p(x) = p^{x} (1-p)^{1-x}$は$x=1$である確率が$p$、$x=0$である確率が$1-p$であることを表す関数だと考えることができます。

ベルヌーイ分布の期待値

ベルヌーイ分布の期待値$E[X]$は前項で確認した確率関数と期待値の定義式に基づいて下記のように導出することができます。
$$
\large
\begin{align}
E[X] &= \sum_{i=0}^{1} x p(x) \\
&= 0 \cdot p(0) + 1 \cdot p(1) \\
&= p
\end{align}
$$

ベルヌーイ分布の分散

ベルヌーイ分布の分散$V[X]$は$V[X]=E[X^2]-E[X]^2$に基づいて下記のように導出することができます。
$$
\large
\begin{align}
E[X^2] &= \sum_{i=0}^{1} x^2 p(x) \\
&= 0^2 \cdot p(0) + 1^2 \cdot p(1) \\
&= p \\
V[X] &= E[X^2] – E[X]^2 \\
&= p – p^2 \\
&= p(1-p)
\end{align}
$$

$V[X]=E[X^2]-E[X]^2$の導出に関しては下記で詳しく取り扱いました。

フロベニウスの同伴行列(companion matrix)の定義と応用

上記でまとめたメルセンヌ・ツイスタ(Mersenne Twister)法ではフロベニウスの同伴行列(companion matrix)が用いられます。当記事では同伴行列の定義と応用に関して取りまとめを行いました。

・数学まとめ
https://www.hello-statisticians.com/math_basic

同伴行列の概要

同伴行列(companion matrix)の定義

フロベニウスの同伴行列(companion matrix)は下記のように定められる。
$$
\large
\begin{align}
C_{n} = \left(\begin{array}{cccccc} 0 & 1 & 0 & \cdots & \cdots & 0 \\ 0 & 0 & 1 & 0 & \cdots & 0 \\ \vdots & \vdots & \ddots & \ddots & \ddots & \vdots \\ 0 & 0 & \cdots & 0 & 1 & 0 \\ 0 & 0 & \cdots & \cdots & 0 & 1 \\ -c_0 & -c_1 & \cdots & \cdots & -c_{n-2} & -c_{n-1} \end{array} \right)
\end{align}
$$

同伴行列と固有多項式

下記のように$n$次多項式$p(\lambda)$を定める。
$$
\large
\begin{align}
p(\lambda) = c_0 + c_1 \lambda + c_2 \lambda^2 + \cdots + c_{n-1} \lambda^{n-1} + \lambda^{n}
\end{align}
$$

以下、$p(\lambda)=0$と$\det{(\lambda I_n – C_n)}=0$が同値であることを示す。$\det{(\lambda I_n – C_n)}$は余因子展開を用いて下記のように変形できる。
$$
\begin{align}
& \det{(\lambda I_n – C_n)} = \left| \begin{array}{cccccc} \lambda & -1 & 0 & \cdots & \cdots & 0 \\ 0 & \lambda & -1 & 0 & \cdots & 0 \\ \vdots & \vdots & \ddots & \ddots & \ddots & \vdots \\ 0 & 0 & \cdots & \lambda & -1 & 0 \\ 0 & 0 & \cdots & \cdots & \lambda & -1 \\ c_0 & c_1 & \cdots & \cdots & c_{n-2} & \lambda+c_{n-1} \end{array} \right| \\
&= \lambda (-1)^{1+1} \left| \begin{array}{cccccc} \lambda & -1 & 0 & \cdots & \cdots & 0 \\ 0 & \lambda & -1 & 0 & \cdots & 0 \\ \vdots & \vdots & \ddots & \ddots & \ddots & \vdots \\ 0 & 0 & \cdots & \lambda & -1 & 0 \\ 0 & 0 & \cdots & \cdots & \lambda & -1 \\ c_1 & c_2 & \cdots & \cdots & c_{n-2} & \lambda + c_{n-1} \end{array} \right| + c_0 (-1)^{n+1} \left| \begin{array}{ccccc} -1 & 0 & \cdots & \cdots & 0 \\ \lambda & -1 & 0 & \cdots & 0 \\ \vdots & \ddots & \ddots & \ddots & \vdots \\ 0 & \cdots & \lambda & -1 & 0 \\ 0 & \cdots & \cdots & \lambda & -1 \end{array} \right| \\
&= \lambda (-1)^{1+1} \left| \begin{array}{cccccc} \lambda & -1 & 0 & \cdots & \cdots & 0 \\ 0 & \lambda & -1 & 0 & \cdots & 0 \\ \vdots & \vdots & \ddots & \ddots & \ddots & \vdots \\ 0 & 0 & \cdots & \lambda & -1 & 0 \\ 0 & 0 & \cdots & \cdots & \lambda & -1 \\ c_1 & c_2 & \cdots & \cdots & c_{n-2} & \lambda + c_{n-1} \end{array} \right| + c_0 (-1)^{n+1+(n-1)} \\
&= \lambda \left| \begin{array}{cccccc} \lambda & -1 & 0 & \cdots & \cdots & 0 \\ 0 & \lambda & -1 & 0 & \cdots & 0 \\ \vdots & \vdots & \ddots & \ddots & \ddots & \vdots \\ 0 & 0 & \cdots & \lambda & -1 & 0 \\ 0 & 0 & \cdots & \cdots & \lambda & -1 \\ c_1 & c_2 & \cdots & \cdots & c_{n-2} & \lambda + c_{n-1} \end{array} \right| + c_0 \\
&= \lambda^2 (-1)^{1+1} \left| \begin{array}{cccccc} \lambda & -1 & 0 & \cdots & \cdots & 0 \\ 0 & \lambda & -1 & 0 & \cdots & 0 \\ \vdots & \vdots & \ddots & \ddots & \ddots & \vdots \\ 0 & 0 & \cdots & \lambda & -1 & 0 \\ 0 & 0 & \cdots & \cdots & \lambda & -1 \\ c_2 & c_3 & \cdots & \cdots & c_{n-2} & \lambda + c_{n-1} \end{array} \right| + c_1 \lambda + c_0 \\
&= \lambda^3 (-1)^{1+1} \left| \begin{array}{cccccc} \lambda & -1 & 0 & \cdots & \cdots & 0 \\ 0 & \lambda & -1 & 0 & \cdots & 0 \\ \vdots & \vdots & \ddots & \ddots & \ddots & \vdots \\ 0 & 0 & \cdots & \lambda & -1 & 0 \\ 0 & 0 & \cdots & \cdots & \lambda & -1 \\ c_2 & c_3 & \cdots & \cdots & c_{n-2} & \lambda + c_{n-1} \end{array} \right| + c_2 \lambda^2 + c_1 \lambda + c_0 \\
&= \; \cdots \\
&= c_0 + c_1 \lambda + c_2 \lambda^2 + \cdots + c_{n-1} \lambda^{n-1} + \lambda^{n}
\end{align}
$$

上記より$p(\lambda)=0 \iff \det{(\lambda I_n – C_n)}=0$であることが確認できる。

参考

・Wikipedia:同伴行列
・線形空間と固有値の応用

Pythonを用いた2進数(binary number)などの表記とビット演算

近年のPCの高性能化に伴い計算処理を直感的に行えるようになった一方で、$2$進数(binary number)やビット演算のようなコンピュータの基本演算は抑えておくと良いです。当記事ではPythonを用いた$2$進数の取り扱いやビット演算に関して取り扱いました。

・Python入門まとめ
https://www.hello-statisticians.com/python_basic

仕組み・原理の理解

2進数

通常数を数えるにあたっては$0$〜$9$の数に基づく$10$進数が使われることが多いが、コンピュータでは$0,1$に基づく$2$進数を元に数字が表されることが多い。有名な例を挙げると、ファミコンのようなゲームに用いられた$8$bitは$2^8=256$に基づいて$0$〜$255$の数字を表すことができる。

プログラムを行う際は整数を取り扱うint型は$4$byteであることが多く、$1$byteは$8$bitであることからint型は$2^{4 \times 8}=4,294,967,296$種類の数字を取り扱える。以下、$2$進数表記と$10$進数表記の対応に関して具体的な数値を元に確認を行う。

$2$進数表記と$10$進数表記を判別するにあたって、以下では$2$進数表記を$1011_{(2)}$のように表す。$1011_{(2)}$のような表記を元に、$3, 5, 10, 15, 20$はそれぞれ下記のように表せる。
$$
\large
\begin{align}
3 &= 11_{(2)} \\
5 &= 101_{(2)} \\
10 &= 1001_{(2)} \\
15 &= 1111_{(2)} \\
20 &= 10100_{(2)}
\end{align}
$$

上記の$3 = 11_{(2)}$は$10$進数表記の$3$と$2$進数表記の$11_{(2)}$の対応の式だが、$3 \times 10^{0} = 1 \times 2^{1} + 1 \times 2^{0}$に基づいて理解することができる。同様に$5 \times 10^{0} = 1 \times 2^{2} + 0 \times 2^{1} + 1 \times 2^{0}$のように考えることができる。$10, 15, 20$に関しては下記のような対応が考えられる。
$$
\large
\begin{align}
1 \times 10^{1} + 0 \times 10^{0} &= 1 \times 2^{3} + 0 \times 2^{2} + 0 \times 2^{1} + 1 \times 2^{0} \\
1 \times 10^{1} + 5 \times 10^{0} &= 1 \times 2^{3} + 1 \times 2^{2} + 1 \times 2^{1} + 1 \times 2^{0} \\
2 \times 10^{1} + 0 \times 10^{0} &= 1 \times 2^{4} + 0 \times 2^{3} + 1 \times 2^{2} + 0 \times 2^{1} + 0 \times 2^{0}
\end{align}
$$

ビット演算

$2$進数の演算は$10$進数の演算と同様な演算を行う場合もあるが、数字単位で演算を行う場合もある。$2$進数表記の場合、数字の$1$つがビットに対応するので、ビット単位の演算であると考えることもできる。

$$
\large
\begin{align}
10 &= 1001_{(2)} \\
15 &= 1111_{(2)}
\end{align}
$$
ビット演算でよく用いるのがANDORXORの$3$つであるので、下記で$3$つの演算を上記の例を元に確認を行う。

AND

ANDは対応する$2$つのビットがどちらも$1$ならば$1$、それ以外の場合は$0$を返す演算である。$1001_{(2)} \; \mathrm{AND} \; 1111_{(2)}$の場合は下記が出力される。
$$
\large
\begin{align}
1001_{(2)} \; \mathrm{AND} \; 1111_{(2)} = 1001_{(2)}
\end{align}
$$

Pythonを用いる場合、AND演算は&で表され、たとえばprint(10 & 15)を実行すると10が出力される。

OR

ORは対応する$2$つのビットがどちらも$1$ならば$1$、それ以外の場合は$0$を返す演算である。$1001_{(2)} \; \mathrm{OR} \; 1111_{(2)}$の場合は下記が出力される。
$$
\large
\begin{align}
1001_{(2)} \; \mathrm{OR} \; 1111_{(2)} = 1111_{(2)}
\end{align}
$$

Pythonを用いる場合、OR演算は|で表され、たとえばprint(10 | 15)を実行すると15が出力される。

XOR

XORは対応する$2$つのビットがどちらも同じ値ならば$0$、それ以外の場合は$1$を返す演算である。$1001_{(2)} \; \mathrm{XOR} \; 1111_{(2)}$の場合は下記が出力される。
$$
\large
\begin{align}
1001_{(2)} \; \mathrm{XOR} \; 1111_{(2)} = 0110_{(2)}
\end{align}
$$

Pythonを用いる場合、XOR演算は^で表され、たとえばprint(10 ^ 15)を実行すると5が出力される。

Pythonプログラムを用いた演算

2進数・8進数・16進数表記

$2$進数・$8$進数・$16$進数はそれぞれbinocthexを用いることで表すことができる。

print(bin(5))
print(oct(10))
print(hex(257))

・実行結果

0b101
012
0x101

$2$進数は0b、$8$進数は0、$16$進数は0xのような接頭辞がついたことを確認しておくと良い。

逆に$2$進数・$8$進数・$16$進数表記から$10$進数表記に戻す際はintを用いれば良い。

print(int(0b101))
print(int(012))
print(int(0x101))

・実行結果

5
10
257

ビット演算子

PythonではAND演算が&OR演算が|XOR演算が^で表される。以下、$7=111_{(2)}$と$5=101_{(2)}$のビット演算に関して確認を行う。

print(7 & 5)
print(7 | 5)
print(7 ^ 5)

・実行結果

5
7
2

上記の結果は$7=111_{(2)}$と$5=101_{(2)}$を対応させることで理解できる。

ビットのシフト

ビットのシフトは>><<で表される。たとえば7 >> 1は$7=111_{(2)}$を右に$1$シフトさせるので$11_{(2)}=3$が得られる。下記より実行例を確認できる。

print(7>>1)
print(15>>1)
print(3<<1)

・実行結果

3
7
6

線形合同法(linear congruential method)における多次元疎結晶構造

整数の合同式に基づく線形合同法はシンプルでわかりやすい乱数生成方法である一方で、多次元分布を考える際に多次元疎結晶構造を生じるという課題があることに注意が必要です。当記事では線形合同法における多次元疎結晶構造をPythonなどを用いて図示を行いました。

・乱数生成の基本アルゴリズムまとめ
https://www.hello-statisticians.com/explain-terms-cat/random_sampling1.html

「自然科学の統計学」の$11$章「乱数の性質」の解説などを参考に作成を行いました。

線形合同法における多次元疎結晶構造

線形合同法に基づく多次元の乱数の作成

$$
\large
\begin{align}
x_{n+1} = ax_{n} + c \quad (\mathrm{mod} \; M), \quad n \geq 1 \quad (1)
\end{align}
$$

上記の式で表される線形合同法を用いて多次元の乱数を作成することを考える。たとえば$M=16, a=5, c=1$の設定に対し、$x_0=0$を考えると下記のように乱数が生成される。
$$
\large
\begin{align}
x_1 &= 1, \, x_2 = 6, \, x_3 = 15, \, x_4 = 12, \, x_5 = 13, \\
x_6 &= 2, \, x_7 = 11, \, x_8 = 8, \, x_9 = 9, \, x_{10} = 14, \\
x_{11} &= 7, \, x_{12} = 4, \, x_{13} = 5, \, x_{14} = 10, \, x_{15} = 3, \\
x_{16} &= 0, \, x_{17} = 1, \, x_{18} = 6, \, x_{19} = 15, \, x_{20} = 12, \\
x_{21} &= 13, \, \cdots
\end{align}
$$

上記の周期は$M=16$に一致する。このように$M=2^n, a=4l+1, c=2l+1$に基づいて乱数を生成する場合、乱数の周期は$M=2^n$に一致するが、詳しくは下記で示した。

ここで$x_0=0, y_0=1$を元に$2$次元の一様乱数を生成することを考える。このとき、$y_0=x_1$であるので、乱数列${ x_n }$から隣接する$2$つの項を取り出し、$2$次元の乱数と見なしたと考えても同義である。

上記のように$2$つの乱数$(x_i,y_i=x_{i+1})$を生成し、$2$次元の一様分布と考えるというのは乱数生成における一般的な考え方である。一方で線形合同法でこのような方法で$2$次元の乱数を生成すると次節で取り扱う多次元疎結晶構造が生じるので注意が必要である。

多次元疎結晶構造

前節のように$M=16, a=5, c=1$の設定に基づいて初期値$x_0=0$から$(1)$式に基づいて乱数を生成した場合を考える。このとき、下記を実行することで$(x_i,x_{i+1})$を$2$次元平面状にプロットすることができる。

import numpy as np
import matplotlib.pyplot as plt

x = np.array([0., 1., 6., 15., 12., 13., 2., 11., 8., 9., 14., 7., 4., 5., 10., 3., 0.])

plt.scatter(x[:-1], x[1:])
plt.show()

・実行結果

上図のように線形合同法を用いて$2$次元乱数を生成すると生成される乱数はいくつかの直線上に規則的に並ぶ。同様の事象が$k$次元の乱数を考えた際にも生じ、このことを多次元疎結晶構造という。多次元疎結晶構造であるかどうかを調べるにあたってはスペクトル検定などが用いられる。

多次元疎結晶構造やスペクトル検定に関しては「自然科学の統計学」の$11$章付節の「多次元疎結晶構造とスペクトル検定」を参照すると詳しい。

Pythonを用いた確認

一様乱数の生成に用いる線形合同法(LCG)の最大周期の法則の証明

一様乱数を生成する手法は様々ですが、乱数の生成の際には乱数の周期に注意が必要です。当記事では一様乱数の生成にあたっての原始的かつシンプルな手法である線形合同法に基づいて乱数を生成する際に、最大周期を実現するにあたってのパラメータの設定とその導出について取りまとめを行いました。

・乱数生成の基本アルゴリズムまとめ
https://www.hello-statisticians.com/explain-terms-cat/random_sampling1.html

前提の確認

線形合同法の概要

$$
\large
\begin{align}
x_{n+1} \equiv a x_{n} + c \quad (\mathrm{mod} \; M), \quad n \geq 1
\end{align}
$$

上記の式に基づいて一様乱数を生成する手法を線形合同法(LCG)という。詳しくは下記で取り扱った。

線形合同法による乱数列の最大周期

線形合同法では$\mathrm{mod} \; M$を考えるが$M$で割った余りは$0$から$M-1$の$M$通りである。よって線形合同法による乱数列の上限は$M$である。$M$はあくまで上限であり、たとえば$M=8,a=2,c=2$の場合は偶数しか生成されないので周期は$M$に一致しないことに注意が必要である。

逆に生成される乱数列が$M$に近い周期を持つ場合はすぐれた設定であると解釈できる。一方で$a=1,c=1$の場合は周期は$M$に一致するが、$1,2,3,4,5,\cdots$のように連番であり、良い乱数列であると言えない。このように$M,a,c$の設定は乱数生成の質に関わる重要な作業であると理解しておくと良い。

最大周期をもたらす設定とその証明

$M=2^n, \, a=4l+1, \, c=2m+1$

周期が$2^{n}$であることの証明

整数$l,m,n$を用いて$M=2^n, \, a=4l+1, \, c=2m+1$のように設定される場合に、生成される乱数列の周期は最大周期$M=2^n$に一致する。以下このことを数学的帰納法を用いて証明する。

i) $n=1,M=2^1=2$の場合
線形合同法における漸化式は下記のように表される。
$$
\large
\begin{align}
a x_{i} + c &= (4l+1) x_i + 2m + 1 \\
&= 2(2l x_i + m) + x_n + 1 \\
& \equiv x_i + 1 \equiv x_{i+1} \quad (\mathrm{mod} \; M)
\end{align}
$$

上記より$\mathrm{mod} \; M$で$x_{i+1} \equiv x_i + 1$が成立することより、$2$で割った余りに$0,1$が交互に出現すると考えることができる。よって$n=1$のとき$M=2^n, \, a=4l+1, \, c=2m+1$の設定における最大周期は$M$である。

ⅱ) $n=k,M=2^k$で成立する場合に$n=k+1,M=2^{k+1}$で成立するか
$2$で割った余りが$0,1$で循環する場合、$4$で割った余りが$0,0,0,\cdots$や$1,1,1,\cdots$にはなり得ない。同様に、「①$n=k,M=2^k$で成立する場合は、$\mathrm{mod} \; 2^{k+1}$を考えても$M=2^k$の周期よりも小さくなることはない」。

次に、「②$n=k,M=2^k$で成立する場合は、$x_i=j, \, 0 \leq j \leq 2^{k}-1$と$x_i=2^{k}+j$に対する$\mathrm{mod} \; 2^{k+1}$での$x_{j+1}$が異なる」ことを示す。
・$x_i=j$のとき
$$
\large
\begin{align}
a x_{i} + c = (4l+1)j + 2m + 1
\end{align}
$$

・$x_i=2^{k}+j$のとき
$$
\large
\begin{align}
a x_{i} + c &= (4l+1)(2^{k}+j) + 2m + 1 \\
&= 2^{k+2} + 2^{k} + (4l+1)j + 2m + 1 \\
& \equiv 2^{k} + (4l+1)j + 2m + 1 \quad (\mathrm{mod} \; 2^{k+1})
\end{align}
$$

$2^{k} + (4l+1)j + 2m + 1-((4l+1)j + 2m + 1)=2^{k}$であることから、$\mathrm{mod} \; 2^{k+1}$では「$x_i=j$と$x_i=2^{k}+j$に対する$x_{j+1}$が異なる」ことが示される。

①と②が成立するので「$n=k,M=2^k$で成立するとき$M=2^{k+1}$を考えると周期$2^k$の乱数列が並ぶか周期$2^{k+1}$の乱数列が並ぶかのどちらかである」と考えることができ、下記のように図示できる。

上図が成立することから、「③$x_i=0$のとき$x_{i+2^{2^{k}}} \neq x_i$」を示せば乱数列の周期が$2^{k+1}$であることを示すことができる。$x_i=0$のとき$x_{i+2^{2^{k}}}$は下記のように表せる。
$$
\large
\begin{align}
x_{i+2^{2^{k}}} – \frac{2m+1}{4l} & \equiv (4l+1)^{2^{k}} \left( x_0 – \frac{2m+1}{4l} \right) \\
&= – \frac{2m+1}{4l}(4l+1)^{2^{k}} \\
&= – \frac{2m+1}{4l} \sum_{j=0}^{2^{k}} {}_{2^{k}} C_{j} (4l)^{j} \\
x_{i+2^{2^{k}}} &= \frac{2m+1}{4l} – \frac{2m+1}{4l} \sum_{j=0}^{2^{k}} {}_{2^{k}} C_{j} (4l)^{j} \\
&= – \frac{2m+1}{4l} \sum_{j=1}^{2^{k}} {}_{2^{k}} C_{j} (4l)^{j} \\
& \equiv – \frac{2m+1}{4l} \times {}_{2^{k}} C_{1} (4l)^{1} \\
& \equiv -2^{k}(2m+1) \\
& \equiv 2^{k}
\end{align}
$$

よって③が成立する。①、②、③より「$n=k,M=2^k$周期が$2^{k}$が成立する場合に$n=k+1,M=2^{k+1}$で周期が$2^{k+1}$」が成立する。i)、ⅱ)より任意の自然数$n$に関して「$M=2^n, \, a=4l+1, \, c=2m+1$」の設定の周期が$2^n$であることが示される。

$M=2^n, \, a=4l+1, \, c=2m+1$の設定の注意点

前項の導出では数学的帰納法を用いたが、i)で確認したように$x_i$を$2$で割った余りが$0,1,0,1,0,\cdots$のように繰り返す。よってこの設定に基づいて生成される乱数は偶数と奇数が交互に入れ替わる乱数となる。

乱数の生成にあたっては可能な限り規則性のない数の並びを生成する必要があることから、「偶奇が必ず入れ替わる」のはそれほど良い乱数列ではないことに注意が必要である。

参考

・自然科学の統計学 Ch$.11$:乱数の性質

メルセンヌ・ツイスタ(Mersenne Twister)法まとめ

当記事では乱数生成にあたって近年用いられることの多いメルセンヌ・ツイスタ(Mersenne Twister)法の仕組みなどについて取りまとめを行いました。メルセンヌ・ツイスタ法はGFSRやTwisted GFSRが元になるので、合わせて取り扱いました。

・乱数生成まとめ
https://www.hello-statisticians.com/explain-terms-cat/random_sampling1.html

原理の理解

M系列

$$
\large
\begin{align}
a_{n} = a_{n-q}+a_{n-p} \quad (\mathrm{mod} \; 2, \; q<p)
\end{align}
$$

$M$系列では上記のような漸化式に基づき乱数列を生成し、連続する$a_n$をビットと見なし乱数生成を行う。数列${a_n}$から連続する$2$つの数字を$2$ビットと見なし乱数を生成する方法は下記で詳しく取り扱った。

M系列に関しては「自然科学の統計学」の$11$章が詳しいので合わせて参照すると良い。

LFSR法

LFSR($1965$)はLinear Feedbacked Shift Registerの略であり、Tauswortheにより発表されたことからTausworthe法ともいわれる。要出典・要確認だが、基本的には前項のM系列と同様であると考えて良いと思われる。

GFSR

Lewis-PayneによるGFSR($1973$)はLFSRの数列をベクトル列に変えた手法である。GFSRはGeneral Feedbacked Shift Registerの略であり、LFSR法を発展させた手法であることが名称からも読み取れる。
$$
\large
\begin{align}
\vec{x}_{n+p} \equiv \vec{x}_{n+q} + \vec{x}_{n} \quad (\mathrm{mod} \; 2, \; q<p)
\end{align}
$$

GFSRのベクトル漸化式は上記のように表されるが、式だけではわかりにくいので以下、具体的な数字に基づいて計算を行う。GFSR論文のFig.$4$を参考に、$p=5, q=2$のとき$\vec{x}_{0}^{\mathrm{T}}$〜$\vec{x}_{4}^{\mathrm{T}}$を下記のように定める。
$$
\large
\begin{align}
\vec{x}_{0}^{\mathrm{T}} &= \left( \begin{array}{c} 1 \\ 1 \\ 0 \\ 1 \\ 0 \end{array} \right), \quad \vec{x}_{1}^{\mathrm{T}} = \left( \begin{array}{c} 1 \\ 0 \\ 0 \\ 0 \\ 1 \end{array} \right), \quad \vec{x}_{2}^{\mathrm{T}} = \left( \begin{array}{c} 1 \\ 1 \\ 0 \\ 1 \\ 1 \end{array} \right) \\
\vec{x}_{3}^{\mathrm{T}} &= \left( \begin{array}{c} 1 \\ 1 \\ 1 \\ 0 \\ 0 \end{array} \right), \quad \vec{x}_{4}^{\mathrm{T}} = \left( \begin{array}{c} 1 \\ 0 \\ 0 \\ 1 \\ 1 \end{array} \right)
\end{align}
$$

このとき$\vec{x}_{5}^{\mathrm{T}}$〜$\vec{x}_{7}^{\mathrm{T}}$はそれぞれ下記のように計算できる。

・$\vec{x}_{5}^{\mathrm{T}}$
$$
\large
\begin{align}
\vec{x}_{0+5} &= \vec{x}_{0+2} + \vec{x}_{0} \\
&= \left( \begin{array}{c} 1 \\ 1 \\ 0 \\ 1 \\ 1 \end{array} \right) + \left( \begin{array}{c} 1 \\ 1 \\ 0 \\ 1 \\ 0 \end{array} \right) \\
&= \left( \begin{array}{c} 0 \\ 0 \\ 0 \\ 0 \\ 1 \end{array} \right) \quad (\mathrm{mod} \; 2)
\end{align}
$$

・$\vec{x}_{6}^{\mathrm{T}}$
$$
\large
\begin{align}
\vec{x}_{1+5} &= \vec{x}_{1+2} + \vec{x}_{1} \\
&= \left( \begin{array}{c} 1 \\ 0 \\ 0 \\ 0 \\ 1 \end{array} \right) + \left( \begin{array}{c} 1 \\ 1 \\ 1 \\ 0 \\ 0 \end{array} \right) \\
&= \left( \begin{array}{c} 0 \\ 1 \\ 1 \\ 0 \\ 1 \end{array} \right) \quad (\mathrm{mod} \; 2)
\end{align}
$$

・$\vec{x}_{7}^{\mathrm{T}}$
$$
\large
\begin{align}
\vec{x}_{2+5} &= \vec{x}_{2+2} + \vec{x}_{2} \\
&= \left( \begin{array}{c} 1 \\ 0 \\ 0 \\ 1 \\ 1 \end{array} \right) + \left( \begin{array}{c} 1 \\ 1 \\ 0 \\ 1 \\ 1 \end{array} \right) \\
&= \left( \begin{array}{c} 0 \\ 1 \\ 0 \\ 0 \\ 0 \end{array} \right) \quad (\mathrm{mod} \; 2)
\end{align}
$$

ここまでの結果はGFSR論文のFig.$4$に一致する。

GFSR論文 Fig.$4$

Twisted GFSR

$$
\large
\begin{align}
\vec{x}_{n+p} &= \vec{x}_{n+q} + \vec{x}_{n} A \quad (\mathrm{mod} \; 2, \; q<p) \\
A &= \left( \begin{array}{ccccc} & 1 & & \cdots & \\ & & 1 & & \\ & & & \ddots & \\ & & & & 1 \\ a_0 & a_1 & \cdots & \cdots & a_{w-1} \end{array} \right)
\end{align}
$$

Twisted GFSR法ではGFSR法の漸化式の一部をフロベニウスの同伴行列(companion matrix)の$A$で攪拌させることで周期の上限が$2^{p}-1$であるGFSR法に対し、周期の上限が$2^{wp}-1$を実現できる。詳しい処理は次節でプログラムを元に確認を行った。

上記で定めたフロベニウスの同伴行列(companion matrix)の$A$に関しては、下記で詳しく取り扱った。

メルセンヌ・ツイスタ法

$$
\large
\begin{align}
\vec{x}_{n+p} = \vec{x}_{n+q} + \vec{x}_{n+1} B + \vec{x}_{n} C \quad (\mathrm{mod} \; 2, \; q<p)
\end{align}
$$

メルセンヌ・ツイスタ法は上記の漸化式で表される。$B, C$に関しては「$\vec{x}_{n+1} B + \vec{x}_{n} C$」が「$\vec{x}_{n}$の上位$w-r$ビットと$\vec{x}_{n+1}$の下位$r$ビットで構成したビットを$\vec{x}_{n}’$とおくとき、$\vec{x}_{n}’=(\vec{x}_{n+1} B + \vec{x}_{n} C)A$が成立するような行列」と理解すると良い。このように生成した乱数は$2^{wp-r}-1$の最大周期を実現できる。

ここで$2^{wp-r}-1=2^{624 \times 32 – 31}-1 = 2^{19937}-1$のようにメルセンヌ素数を用いることができ、このことにより超長周期を実現することができる。メルセンヌ素数に関しては下記で詳しく取り扱った。

プログラム

Twisted GFSR

Cのプログラムの確認

/* A C-program for TT800 : July 8th 1996 Version */
/* by M. Matsumoto, email: matumoto@math.keio.ac.jp */
/* genrand() generate one pseudorandom number with double precision */ /* which is uniformly distributed on [0,1]-interval */
/* for each call. One may choose any initial 25 seeds */
/* except all zeros. */
/* See: ACM Transactions on Modelling and Computer Simulation, */
/* Vol. 4, No. 3, 1994, pages 254-266. */
#include <stdio.h>
#define N 25
#define M 7

double
genrand()
{
    unsigned long y;
    static int k = 0;
    static unsigned long x[N]={ /* initial 25 seeds, change as you wish */
        0x95f24dab, 0x0b685215, 0xe76ccae7, 0xaf3ec239, 0x715fad23,
        0x24a590ad, 0x69e4b5ef, 0xbf456141, 0x96bc1b7b, 0xa7bdf825,
        0xc1de75b7, 0x8858a9c9, 0x2da87693, 0xb657f9dd, 0xffdc8a9f,
        0x8121da71, 0x8b823ecb, 0x885d05f5, 0x4e20cd47, 0x5a9ad5d9,
        0x512c0c03, 0xea857ccd, 0x4cc1d30f, 0x8891a8a1, 0xa6b7aadb
    };
    static unsigned long mag01[2]={
        0x0, 0x8ebfd028 /* this is magic vector ‘a’, don’t change */
    };
    if (k==N) { /* generate N words at one time */
      int kk;
      for (kk=0;kk<N-M;kk++) {
        x[kk] = x[kk+M] ^ (x[kk] >> 1) ^ mag01[x[kk] % 2];
      }
      for (; kk<N;kk++) {
        x[kk] = x[kk+(M-N)] ^ (x[kk] >> 1) ^ mag01[x[kk] % 2];
      }
k=0; }
    y = x[k];
    y ^= (y << 7) & 0x2b5b2500; /* s and b, magic vectors */
    y ^= (y << 15) & 0xdb8b0000; /* t and c, magic vectors */
    y &= 0xffffffff; /* you may delete this line if word size = 32 */
    y ^= (y >> 16); /* added to the 1994 version */
    k++;
    return( (double) y / (unsigned long) 0xffffffff);
}
/* this main() output first 50 generated numbers */
main()
{ int j;
  for (j=0; j<50; j++) {
    printf("%5f ", genrand());
    if (j%8==7) printf("\n");
}
  printf("\n");
}

講義資料:有限体の擬似乱数への応用

上記のプログラムのx[N]は乱数の初期シード、mag01[2]は同伴行列$A$の$a_0, \cdots a_{w-1}$にそれぞれ対応する。mag01[2]に関して”this is magic vector ‘a’, don’t change”とあるので、同伴行列は乱数生成の際は固定であることが確認できる。

また、0x95f24dab0xは$16$進数であることを意味しており、$0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f$の$16$個の文字が用いられる。

ここまで確認した内容により、同伴行列の構成と乱数の初期値が得られるので、次項では前節で確認した漸化式と当項で確認した同伴行列や乱数の初期値を元にPythonで乱数生成を行う。

Pythonでの再現

Twisted GFSR法はPythonを用いて下記のように再現することができる。

import numpy as np
import matplotlib.pyplot as plt

init_x = [bin(0x95f24dab), bin(0x0b685215), bin(0xe76ccae7), bin(0xaf3ec239), bin(0x715fad23), bin(0x24a590ad), bin(0x69e4b5ef), bin(0xbf456141), bin(0x96bc1b7b), bin(0xa7bdf825), bin(0xc1de75b7), bin(0x8858a9c9), bin(0x2da87693), bin(0xb657f9dd), bin(0xffdc8a9f), bin(0x8121da71), bin(0x8b823ecb), bin(0x885d05f5), bin(0x4e20cd47), bin(0x5a9ad5d9), bin(0x512c0c03), bin(0xea857ccd), bin(0x4cc1d30f), bin(0x8891a8a1), bin(0xa6b7aadb)]

x = np.zeros([100000, 2**5])
for i in range(len(init_x)):
    init_num = 2**5-len(list(init_x[i][2:]))
    x[i,init_num:] = np.array(list(init_x[i][2:]))

a = bin(0x8ebfd028)
init_num_a = 2**5-len(list(a[2:]))
A = np.zeros([2**5, 2**5])
for i in range(A.shape[0]-1):
    A[i,i+1] = 1.

A[-1,init_num_a:] = np.array(list(a[2:]))

for i in range(x.shape[0]-25):
    x[i+25,:] = (x[i+7,:] + np.dot(x[i,:],A))%2

numbers = np.zeros(x.shape[0])
for i in range(x.shape[0]):
    for j in range(x.shape[1]):
        numbers[i] += x[i,j]*2**(2**5-1-j)

plt.hist(numbers%100, bins=100)
plt.show()

・実行結果

妥当な一様乱数が得られたかどうかを大まかに確認するにあたって、上記では得られた乱数を$100$で割った余りに関してヒストグラムの作成を行った。

メルセンヌ・ツイスタ法

Cのプログラムの確認

下記でプログラムが確認できる。
http://www.math.sci.hiroshima-u.ac.jp/m-mat/MT/MT2002/CODES/mt19937ar.c

Pythonでの再現

メルセンヌツイスタ法はPythonを用いて下記のように再現することができる。

import numpy as np
import matplotlib.pyplot as plt

N = 624
M = 397
a = 0x9908b0df

numbers = np.zeros(1000000)

numbers[0] = 19650218 & 0xffffffff
for i in range(1,N):
    numbers[i] = (1566083941 * (int(numbers[i-1]) ^ (int(numbers[i-1]) >> 30)) + i) & 0xffffffff

for i in range(numbers.shape[0]-N):
    num = (int(numbers[i+1]) & 0x7fffffff) + (int(numbers[i]) & 0x80000000)
    if num & 0x1 == 0:
        numbers[i+N] = int(numbers[i+M]) ^ (num >> 1)
    else:
        numbers[i+N] = int(numbers[i+M]) ^ ((num >> 1) ^ a)

plt.hist(numbers%500, bins=500)
plt.show()

・実行結果

初期値の作成が元コードには準拠していないが、乱数生成部分に関しては同様な処理を再現した。実行結果では一様乱数が得られており、概ね妥当な結果が得られたと判断できる。途中の処理で用いたビット演算は下記で詳しく取りまとめた。

参考

・資料:第$50$回市村学術賞記念 先端技術講演会
・講義資料:有限体の擬似乱数への応用
・Wikipedia:メルセンヌ・ツイスタ
・Wikipedia:M系列
・Wikipedia:線形帰還シフトレジスタ
・論文:GFSR
・論文:Twisted GFSR
・論文:メルセンヌ・ツイスタ

メルセンヌ数(Mersenne Number)と完全数(Perfect Number)

乱数生成によく用いられるアルゴリズムのメルセンヌ・ツイスタ法ではメルセンヌ数(Mersenne Number)という概念が用いられます。当記事ではWikipediaなどを参考にメルセンヌ数、メルセンヌ素数、完全数に関して簡単に取りまとめを行いました。

・メルセンヌツイスタ法
https://www.hello-statisticians.com/explain-terms-cat/mersenne_twister1.html

メルセンヌ数・メルセンヌ素数

定義

$$
\large
\begin{align}
M_n = 2^{n}-1, \quad n \in \mathbb{N}
\end{align}
$$

上記のように自然数$n$を用いて$M_n=2^{n}-1$のように表される数をメルセンヌ数という。メルセンヌ数は下記のように具体的に考えることができる。
$$
\large
\begin{align}
2^{1}-1 &= 1 \\
2^{2}-1 &= 3 \\
2^{3}-1 &= 7 \\
2^{4}-1 &= 15 \\
2^{5}-1 &= 31 \\
2^{6}-1 &= 63 \\
2^{7}-1 &= 127 \\
2^{8}-1 &= 255 \\
2^{9}-1 &= 511 \\
2^{10}-1 &= 1023 \\
2^{11}-1 &= 2047
& \vdots
\end{align}
$$

上記に基づいて$M_n$に素数が出てくる場合をメルセンヌ素数(Mersenne prime)という。$M_n$が素数である場合、$n$は素数であるが、逆の「$n$が素数 $\implies$ $M_n$が素数」は成立しない。具体的には下記のように考えられる。

$n=2, M_n=3$$n$と$M_n$のどちらも素数
$n=3, M_n=7$$n$と$M_n$のどちらも素数
$n=5, M_n=31$$n$と$M_n$のどちらも素数
$n=7, M_n=127$$n$と$M_n$のどちらも素数
$n=11, M_n=2047$$n$は素数だが$M_n=2047=23 \times 89$

判定法

桁が小さい数に関しては計算した$M_n$を割り切る数があるかを探せば良いが、「リュカ-レーマー・テスト」を用いることなどによって効率化できる。

メルセンヌ素数の一覧

Wikipedia:メルセンヌ素数の一覧」が詳しいが、$51$個発見されている。

$n \leq 10,000$では$n=2, 3, 5, 7, 13, 17, 19, 31, 61, 89, 107, 127, 521, 607, 1279, 2203, 2281, 3217, 4253, 4423, 9689, 9941$が挙げられる。

完全数

メルセンヌ数$M_n = 2^{n}-1$が素数であるとき、$2^{n-1}(2^{n}-1)$は完全数である。完全数は「正の約数の和に等しい自然数」を定めた数である。前節で確認したメルセンヌ素数$M_n = 2^{n}-1$に関して以下、$2^{n-1}(2^{n}-1)$が完全数であることを確かめる。

$n=2, M_n=3$

$$
\large
\begin{align}
2^{n-1}(2^{n}-1) &= 2^{2-1}(2^{2}-1) \\
&= 2 \times 3 = 6 \\
1 + 2 + 3 &= 6
\end{align}
$$

$n=3, M_n=7$

$$
\large
\begin{align}
2^{n-1}(2^{n}-1) &= 2^{3-1}(2^{3}-1) \\
&= 2^2 \times 7 = 28 \\
1 + 2 + 4 + 7 + 14 &= 28
\end{align}
$$

参考

・Wikipedia:メルセンヌ数
・Wikipedia:完全数
・Wikipedia:メルセンヌ・ツイスタ