Groovy で BigInteger な fact

Groovy は整数リテラルが int ではなく Integer なのですね。

1.class   #=> class java.lang.Integer
1 class   "=> SmallInteger "

でも、Integer.MAX_VALUE + 1 は Integer のままなので、

(Integer.MAX_VALUE + 1).class     #=> class java.lang.Ineger
(SmallInteger maxVal + 1) class   "=> LargePositiveInteger"

fact(100) などはきちんと計算できません。

fact = {| n | (2..n).inject(1) {| f, i | f * i}}
fact.call(10)    #=> 3628800
fact.call(100)   #=> 0
fact
fact := [: n | (2 to: n) inject: 1 into: [: f : i | f * i]]. fact value: 100 "=> 933262154439441526816992388562667004907159682643816214685 9296389521759999322991560894146397615651828625369792082722375 8251185210916864000000000000000000000000

無限精度にするには、java.math.BigInteger を明示的に導入する必要があります。ただ、Java と違って、二項演算子が使えるので初期値の 1 だけ BigInteger にしておけばよいようです。

import java.math.BigInteger
bigFact = {| n | (2..n).inject(BigInteger.ONE) {| f, i | f * i}}
bigFact.call(100)
#=> 933262154439441526816992388562667004907159682643816214685
9296389521759999322991560894146397615651828625369792082722375
8251185210916864000000000000000000000000

追記
BigInteger のリテラルである 1G を代わりに使えば、BigInteger を明示的に import する必要はないようです。

bigFact = {| n | (2..n).inject(1G) {| f, i | f * i}}
bigFact.call(100)
#=> 933262154439441526816992388562667004907159682643816214685
9296389521759999322991560894146397615651828625369792082722375
8251185210916864000000000000000000000000