バナナでもわかる話

計量経済学・統計学が専門の大学院生です。統計学・経済学・投資理論・マーケティング等々に関する勉強・解説ブログ。ときどき趣味も。極力数式は使わずイメージで説明出来るよう心掛けていますが、時々暴走します。

Rで組み合わせ(choose関数)を使ってInfが出た時の対処法

Rで組み合わせを考える際のパッケージとして基本的なものにchoose関数があります。

例えば \begin{eqnarray*}
  && {}_5 C _2 \\
\end{eqnarray*}のようなものを考える場合には次のように打ち込みます。

> choose(5,2)
[1] 10

スポンサーリンク


しかし、大きな数字でこのコンビネーションを計算しようとすると、大きすぎるのでオーバーフローし、Infとなります。

> choose(20000,210)
[1] Inf

で、どうすんだってことでやり方を探ってみたところ、gmpパッケージってのがあるみたい。

library(gmp)
> chooseZ(20000,210)
Big Integer ('bigz') :
[1] 51702816513240461344443727194665717134330876236797794048015569113579148299385641166#$(収まりきらないので省略)

型はなんだ?とみてみると、bigzという見知らぬ型が。

> is(chooseZ(20000,210))
[1] "bigz"     "oldClass"

計算は出来るのか?と思って色々やってみる
足し算引き算は出来て、numeric型を足すことも出来るっぽい。

> chooseZ(20000,210)-chooseZ(20000,210)+1
Big Integer ('bigz') :
[1] 1

多分integerにしか対応してないだろうから、小数は無理だろうなと思いつつ

> chooseZ(2,1)
Big Integer ('bigz') :
[1] 2
> chooseZ(2,1)+0.1
Big Integer ('bigz') :
[1] 2
> chooseZ(2,1)+0.5
Big Integer ('bigz') :
[1] 2
> chooseZ(2,1)+0.9
Big Integer ('bigz') :
[1] 2
> chooseZ(2,1)+1.1
Big Integer ('bigz') :
[1] 3
> chooseZ(2,1)-1.1
Big Integer ('bigz') :
[1] 1

足したり引いたりしても小数点以下は切り下げられてるっぽい。

掛け算もしてみる

> chooseZ(2,1)*0.1
Big Integer ('bigz') :
[1] 0
> chooseZ(10,1)*0.1
Big Integer ('bigz') :
[1] 0
> chooseZ(100,1)*0.1
Big Integer ('bigz') :
[1] 0

んん!!??問答無用で0になるっぽい。

割り算もしてみる

> chooseZ(100,1)/1
Big Rational ('bigq') :
[1] 100
> chooseZ(100,1)/3
Big Rational ('bigq') :
[1] 100/3
> chooseZ(100,1)/3.2
Big Rational ('bigq') :
[1] 112589990684262400/3602879701896397
> 100/3.2
[1] 31.25
> as.numeric(chooseZ(100,1)/3.2)
[1] 31.25

割り算はいけるっぽい。ただ、出力結果がBig Rationalというよくわかんない形式になるので、試しにas.numericで変換してみたところ一応理論値通りの結果に。
え、じゃあもしかして掛け算を全部分数の割り算にすればうまいこといくのでは?

> as.numeric(chooseZ(100,1)/(1/100.15))
[1] 10015

おぉ~いけるやん。


まとめ

・大きい数字でchoose関数を使う時はgmpパッケージのchooseZ関数
・ただ、基本整数値しか扱えないので、小数の足し算引き算をしない
・小数を掛けたい場合は割り算の形に直してからas.numericするといける