階乗と二重階乗、スターリングの公式

階乗 Factorial

 正の整数 n について

\[n!=n\,(n-1)\,(n-2) \cdots 2 \cdot 1, \quad 0!=1 \tag{1}\]

を n の階乗(factorial)と定義します。たとえば、
 
\[\begin{align*}3!=&\,3 \cdot 2 \cdot 1=6\\[6pt]
5!=&\,5 \cdot 4 \cdot 3 \cdot 2 \cdot 1=120\end{align*}\]
のように計算します。階乗は数学のあらゆる場面で登場します。特に確率論による組合せや オイラー積分(ガンマ関数)、関数の級数展開などの計算で活躍します。

階乗の再帰的定義

 プログラミングなどで階乗を計算させるには再帰的定義を用いると簡単です。

\[n!=\left\{\begin{matrix}1 \qquad \quad \; \qquad(n=0)\\
n(n-1)!\qquad(n\geq1)\end{matrix}\right.\]

 つまり n = 0 の場合だけ特別に 0! = 1 の値を与えて、n > 1 については For文などのループ処理で
 
\[\begin{align*}1!=&1\\[6pt]
2!=&2 \cdot 1!=2\\[6pt]
3!=&3 \cdot 2!=6\\[6pt]
4!=&4 \cdot 3!=24\end{align*}\]
といった具合に計算させます。

xn の導関数による定義

 たとえば x3 を順に微分していくと、
 
\[\begin{align*}&\frac{d(x^3)}{dx}=3x^2\\[6pt]
&\frac{d^2(x^3)}{dx^2}=3 \cdot 2x\\[6pt]
&\frac{d^3(x^3)}{dx^3}=3 \cdot 2 \cdot 1=3!\end{align*}\]
となります。一般に階乗は xn の n階微分によって

\[n!=\frac{d^n}{dx^n}\,x^n\]

と定義することができます。
 

FACT関数

 Excel の FACT(x) は x の階乗を返します。たとえば、セルに

=FACT(10)

と入力すると、$10!$ を計算して 3628800 を返します。階乗の定義にしたがって、FACT(0) は 1 を返します。FACT に負数を渡すとエラーとなります。たとえば、

=FACT(-5)

と入力すると、#NUM! すなわち関数に無効な数値が渡されたことを示すエラーが表示されます。数学では階乗は非負の整数のみに定義されていますが、FACT に小数を渡してもエラーとはなりません。引数の小数部は切り捨てられ、整数部の階乗を返します。たとえば、

=FACT(4.8)

と入力した場合、4 の階乗を計算して 24 を返します。
 

階乗の対数

 $f(n)=\log(n!)$ は指数関数 $g(n)=\exp n$ よりも $n$ に対する増加率の大きな関数です。これを Excel で視覚化したのが下図です ( ≫ この図はこちらからダウンロードできます)。

Excel FACT関数を用いてプロットした階乗の対数

 青い点が $f(n)=\log(n!)$ の散布図です。赤い点で $f(n)=\exp n$ の対数、すなわち、$\log g(n)=n$ をプロットしています。

スターリングの公式

 スターリングの公式
 
\[\Gamma (x+1)\sim \sqrt{2\pi x}x^xe^{-x}\]
を用いると

\[\Gamma (n+1)=n!\sim \sqrt{2\pi n}\left ( \frac{n}{e} \right )^n\]

という階乗についての近似式を得ることができます。この近似は n が大きな値をとるほど精度がよくなります。
 

二重階乗 Double Factorial

 正の整数 n について、

  \(n!!=n\,(n-2)\,(n-4) \cdots 3 \cdot 1\) ( n が奇数のとき)
  \(n!!=n\,(n-2)\,(n-4) \cdots 4 \cdot 2\) ( n が偶数のとき)
  \(0!!=(-1)!!=1\) ( n が 0, -1 のとき)

n の二重階乗(double factorial)と定義します。たとえば、
 
\[7!!=7 \cdot 5 \cdot 3 \cdot 1=105\]
のように計算します。二重階乗はガンマ関数やベッセル関数など特殊関数の計算などで用います。二重階乗は普通の階乗と指数の組合せで表すこともできます。

\[(2m)!!=2^m m!, \qquad (2m-1)!!=\frac{(2m)!}{2^m m!}\]

 証明は簡単です:
 
\[\begin{align*}(2m)!!=&2m\,(2m-2)\,(2m-4) \cdots 4 \cdot 2\\[6pt]
=&2^m\,m\,(m-1)\,(m-2) \cdots 2 \cdot 1=2^m m!\end{align*}\]
 また、$(2m)!!=2^m m!$ の両辺に (2m - 1)!! をかけると、
 
\[(2m)!!(2m - 1)!!=2^m m!(2m - 1)!!\]
 左辺は $(2m)!$ となるので、
 
\[(2m)!=2^m m!(2m - 1)!!\]
 したがって、
 
\[(2m-1)!!=\frac{(2m)!}{2^m m!}\]
が証明されました。たとえば、$m=4$ としてみると、
 
\[7!!=\frac{8!}{2^44!}=\frac{8\cdot 7\cdot 6\cdot 5}{16}=105\]
となります。
 

FACTDOUBLE関数

 Excel の FACTDOUBLE(x) は x の二重階乗を返します。たとえば、

=FACTDOUBLE(8)

と入力すると、$8!!=8\cdot 6\cdot 4\cdot 2$ を計算して 384 を返します。FACTDOUBLE(0) および FACTDOUBLE(1) は 1 を返します。FACTDOUBLE に負数を渡すと、無効な数値が渡されたことを示す #NUM! を返します。FACTDOUBLE に小数を渡した場合、小数部は無視されて、整数部の二重階乗を返します。たとえば、あるセルに

=FACT(5.5)

を入力すると、5 の二重階乗 $5!!=5\cdot 3\cdot 1$ を計算して 15 を返します。
 

[EX-14] Excel で階乗を含む級数を計算します

 Excel を用いて次の級数
\[S=\sum_{k=1}^{10}\frac{k-1}{k!}\]の値を計算して小数点以下 8 桁まで表示させてください。
 

問題 EX-14 のヒント(階乗を計算する関数は?)

 基本問題ですが、階乗計算の関数を使う必要があります。
 

解答 EX-14 (FACT関数と SUM関数で計算します)

 数値の階乗を計算するときは FACT関数を使います。
 たとえば次のようなシートを作って、セル C3 には

=(B3-1)/FACT(B3)

と入力してセル C12 までコピーします。

 Excelで階乗を含む級数(数列の和)を計算
 
 それから数値を合計する SUM関数を使って

=SUM(C3:C12)

と入力すれば求める値が表示されます。最後に計算結果が表示されているセルを右クリックして、[セルの書式設定]、[数値] を順に選択し、小数点以下の桁数を 8 に設定すると

0.99999972

という値が表示されます。ちなみに級数の式を
 
\[S=\sum_{k=1}^n\frac{k-1}{k!}=\sum_{k=1}^n\left(\frac{k}{k!}-\frac{1}{k!}\right)=\sum_{k=1}^n\left\{\frac{1}{(k-1)!}-\frac{1}{k!}\right\}\]
と変形して右辺を具体的に書き表してみると最初と最後の項だけが残り、
 
\[S=\sum_{k=1}^n\frac{k-1}{k!}=1-\frac{1}{n!}\]
となります。つまりある程度 $n$ が大きくなれば、$S\simeq 1$ となるのです。
 

巨大な階乗数 n! を計算するマクロ

 ワークシートでは FACT 関数を用いて

=FACT(数値)

とすれば階乗の値を返してくれますが、数値に 171 以上の値を入れるとエラーになってしまいます。エクセルでは 15 桁までの数しか扱えないからです。そこでこの問題を解決するために階乗の値を
 
\[n!=10^x\]
の形で表すことにして $x$ の部分を求めることにします。
 
\[n! = n(n - 1)(n - 2)\:\cdots\]
ですから $n$ の常用対数をとると
 
\[\log n!=\log n+\log (n-1)+\log (n -2)+\:\cdots\]
と足し算で表すことができます。まずはこの $\log n!$ を求めるプログラムを作ってみます。

 Function LOGFACT(n As Long) As Double

 Dim k As Long
 Dim logef As Double

 If n = 1 Then

  LOGFACT = 0

 'n が 1 より大きな整数であれば以下の処理を行います
 ElseIf n = Int(n) And n > 1 Then

 'n!の自然対数を計算します
  For k = 0 To n - 1
   logef = logef + Log(n - k)
  Next k

 '常用対数に変換します
  LOGFACT = logef / Log(10)

 Else

  LOGFACT = CVErr(xlErrNum)

 End If

 End Function

 たとえばワークシートのセルに

=LOGFACT(1000)

と入力すると 2567.604 ... という値が返ります。これが指数部分 $x$ に相当します。

 n! の対数値を得ることが目的ならこのままでもいいのですが、あくまで n! の値そのものがほしい場合は別の関数を作って処理する必要があります。 $x$ を整数部分 $a$ と小数部分 $b$ に分けると
 
\[n!=10^x=10^{\,a+b}=10^{\,b} \times 10^{\,a}\]
のように書くことができます。 $10^{\,a}$ はただの桁数です。重要なのは $10^{\,b}$ のところですが、これは小さな値なので問題なく計算できます。

 桁数 a を取り出すのには TRUNC 関数を使って

=TRUNC(LOGFACT(数値))

とするだけです。先ほどの例、つまり 1000! の桁数を得るには

=TRUNC(LOGFACT(1000))

と入力すればよく、結果は 2567 となります(ものすごい桁ですね!)。

 POWERDEC という関数を作って $10^{\,b}$ を計算します。

 Function POWERDEC(x As Double) As Double
  POWERDEC = 10 ^ (x - Fix(x))
 End Function

 さきほどの 1000! の例に適用して

=POWERDEC(LOGFACT(1000))

とすると 4.0238726 ... という値を得ることができます。つまり
 
\[1000!=4.023873 \times 10^{\,2567}\]
であることがわかりました。


 

コメント

  1. yumyam より:

    二重階乗を階乗で表します。のところで、
    (2m−1)!! = 2*m/(2^m*m!) とありますが、これは誤りで、
    (2m−1)!! = (2*m)!!/(2*m)! さらに、
    = 2^m*m!/(2*m)! ですよね。

    • Blog Cat より:

      御指摘ありがとうございます。
      誤記を訂正すると同時に、説明不足な箇所は加筆しておきました。
      何しろ一人で書いているので、サイトのあちこちに誤記があると思われます。
      今後も誤りを指摘していただけると幸いです。よろしくお願いします。

コメントをどうぞ

メールアドレスが公開されることはありません。