32ビット整数(int
)で単純に行うことはできません。 64ビットの整数は20!
まで到達しますが、21!
で失敗します。数字はあまりにも大きくなり過ぎます。それ以上に進むには、System.Numerics.BigInteger
(F#でbigint
と略記)を使用する必要があります。
パラメータは、おそらく合理的であるとint
として滞在することができますが、bigint
を返却する必要があります。
let rec Fact (n : int) =
if n = 0 then bigint.One else (bigint n) * Fact (n - 1)
それとももう少し慣用すべき:
let rec Fact = function | 0 -> bigint.One | n -> (bigint n) * Fact (n - 1)
そして今、中あなたのCombo
関数では、これらの数値を内部的にすべての数式に使用する必要があります(ありがたいことに整数除算が必要です)。
let Combo (n : int) (k : int) =
if n = 0 then bigint.Zero else (Fact n)/((Fact k) * (Fact (n - k)))
あなた本当にがCombo
リターンint
を作りたいと思った場合、あなたはここでその変換を行うことができます。
let Combo (n : int) (k : int) =
if n = 0 then 0 else (Fact n)/((Fact k) * (Fact (n - k))) |> int
例:
Combo 20 5 // --> 15504
Combo 99 5 // --> 71523144 (would break if you used int64)
編集:あなたを再考することをCombo
の実装では、いくつかのbを得ることができますこのうちigのパフォーマンスが改善されました。この実装の基礎のためのthis question on Math.SEを参照してください:
let ComboFast (n : int) (k : int) =
let rec Combo_r (n : int) = function
| 0 -> bigint.One
| k -> (bigint n) * (Combo_r (n - 1) (k - 1))/(bigint k)
Combo_r n (if (2 * k) > n then n - k else k)
迅速なベンチマークは、上記Fact
ベースのバージョンよりも大幅に速くするためにこれを示した:!
Function Avg. Time (ms)
Combo 99 5 30.12570
ComboFast 99 5 0.72364
'20'について '2.4 *です10^18'は 'int'よりもかなり大きいので、オーバーフローするという驚きはありません。私はあなたの質問が何かをよく理解していませんが。どちらのタイプを使うべきかを尋ねていますが、同時に別のタイプの使用を拒否しています。ハァッ? –