• ベストアンサー

高機能な表計算ソフトを探しています

5000程度の階乗や順列を使った計算をしたいのですが、 例えば (aPn * bPn) / C! に a,b,C の値を与えて n=1,2...100 でそれぞれ計算して出力する。 EXCELでは、階乗の計算は170程度までしか出来ないので、他にソフトがないか探しています。 お金を出してまで...とは考えていないので、フリーに限ります。 何か、良いものはないでしょうか。よろしくお願い致します。

質問者が選んだベストアンサー

  • ベストアンサー
  • ki073
  • ベストアンサー率77% (491/634)
回答No.1

普通の倍精度浮動小数点の場合は質問者さんが書かれているように170!くらいまでしか計算でしません。 170!で7.257415615308e+306となります。 分母がc!となっていますので、式をうまく変形して大きな数字にならないようにしてやれば可能ですが、 多倍長整数(あるいは浮動小数点数)を扱えるソフトを使えば直接計算できます。 表計算ソフトでは見たことがありません。 例えば、(aPn * bPn) / c!の計算をRubyを使ったプログラムを示しますと a=200 b=300 c=100 (1..100).each{|n| puts (n..a).inject(:*)*(n..b).inject(:*)/(1..c).inject(:*) } のようになります。上の計算式は整数割る整数になっていますので、小数点以下が切り捨てられす。 それをしたくない時は require "rational" a=200 b=300 c=100 (1..100).each{|n| puts Rational((n..a).inject(:*)*(n..b).inject(:*), (1..c).inject(:*)) } とすれば分数計算してくれますし、 puts Rational((n..a).inject(:*)*(n..b).inject(:*), (1..c).inject(:*)).to_f としておけば浮動小数点表示できます。 5000!でも (1..5000).inject(:*) で全桁計算が可能です。ものすごい桁数になりますが。

zggwtyb
質問者

お礼

皆様、回答ありがとうございました。 「LM多倍長電卓」というソフトが見つかり、表計算ソフトではありませんがこれでほぼ目的は達成できるので、今回はこのソフトを使うことにしました。 少し時間ができたら、プログラミングを勉強し直して、これぐらいの計算ならサクサクできるようになりたいと思っています。 いろいろなアドバイスをありがとうございました。

その他の回答 (3)

  • ki073
  • ベストアンサー率77% (491/634)
回答No.4

おはようございます。 Excelのようなものでできる方法を考えてみました。 あくまでも最終の答えがExcelで表示できる範囲であるという条件である必要がありますが。 exp(log(aPn * bPn) / c!) )=exp(log(aPn)+log(bPn)-log(c!)) 要するに一旦対数に変換して、expで戻す方法です。 c!が大きすぎて計算できないときには、 スターリングの近似式を使います。 http://ja.wikipedia.org/wiki/階乗 log(c!) -> 0.5*log(2*PI)+(c+0.5)*log(c)-c*log(E) となります。 あるいは c! -> c!/(c-m)!*(c-m)!/(c-m-k)!*(c-m-k)! -> cPm*(c-m)Pk*(c-m-k)! とオーバーフローしない程度にc!を分割して log(c!) -> log(cPm)+log((c-m)Pk)+log((c-m-k)!) かなりややこしいので計算ミスしている様な気もしますが、できないことはない。

  • ki073
  • ベストアンサー率77% (491/634)
回答No.3

たびたびすみません。 Excelで順列の計算をするのにPERMUTが使えるようですね。 階乗をのようにすごく大きな数にはなりませんので、計算可能かもしれません。 c!はそのままでは 170!までしか計算できませんので、それより大きな場合は、かなり考えないと。 No.1、2に示した方法ではオーバーフローは発生しませんのでお手軽です。 Windowsの場合はRubyをインストールしないといけませんが。 Macの場合は最初から入っていますし、Linuxは簡単に入れられます。

  • ki073
  • ベストアンサー率77% (491/634)
回答No.2

No.1です。式を大間違いしていますね。訂正。 (aPn * bPn) / c!の場合は (a-n+1..a).inject(:*)*(b-n+1..b).inject(:*)/(1..c).inject(:*) ですね。

関連するQ&A