Loading numeric/numeric.go 0 → 100644 +67 −0 Original line number Diff line number Diff line package numeric // Factorial calculates n!. func Factorial(n uint64) uint64 { if n < uint64(len(facsSmall)) { return factorialSmall(n) } return factorialCalc(n) } // Helpers... var ( facsSmall = []struct { n uint64 f uint64 }{ {n: 0, f: 1}, {n: 1, f: 1}, {n: 2, f: 2}, {n: 3, f: 6}, {n: 4, f: 24}, {n: 5, f: 120}, {n: 6, f: 720}, {n: 7, f: 5040}, {n: 8, f: 40320}, {n: 9, f: 362880}, {n: 10, f: 3628800}, {n: 11, f: 39916800}, {n: 12, f: 479001600}, {n: 13, f: 6227020800}, {n: 14, f: 87178291200}, {n: 15, f: 1307674368000}, {n: 16, f: 20922789888000}, {n: 17, f: 355687428096000}, {n: 18, f: 6402373705728000}, {n: 19, f: 121645100408832000}, {n: 20, f: 2432902008176640000}, //{n: 21, f: 51090942171709440000}, } ) func factorialSmall(n uint64) uint64 { if n < uint64(len(facsSmall)) { return facsSmall[int(n)].f } return 0 } func factorialCalc(n uint64) uint64 { var f uint64 = 1 for n > 1 { f *= n n-- } return f } // BinomialCoefficient calculates n over k. func BinomialCoefficient(n, k uint64) uint64 { if k == 0 { return 1 } if n == k { return 1 } return Factorial(n) / (Factorial(k) * Factorial(n-k)) } numeric/numeric_test.go 0 → 100644 +78 −0 Original line number Diff line number Diff line package numeric import ( "testing" ) func TestFactorial(t *testing.T) { for _, tv := range []struct { n uint64 f uint64 }{ {n: 0, f: 1}, {n: 1, f: 1}, {n: 2, f: 2}, {n: 3, f: 6}, {n: 4, f: 24}, {n: 5, f: 120}, {n: 6, f: 720}, {n: 7, f: 5040}, {n: 8, f: 40320}, {n: 9, f: 362880}, {n: 10, f: 3628800}, {n: 11, f: 39916800}, {n: 12, f: 479001600}, {n: 13, f: 6227020800}, {n: 14, f: 87178291200}, {n: 15, f: 1307674368000}, {n: 16, f: 20922789888000}, {n: 17, f: 355687428096000}, {n: 18, f: 6402373705728000}, {n: 19, f: 121645100408832000}, {n: 20, f: 2432902008176640000}, //{n: 21, f: 51090942171709440000}, } { if f := Factorial(tv.n); f != tv.f { t.Errorf("Factorial(%d) is %d, expected %d", tv.n, f, tv.f) } } } func TestFactorial2(t *testing.T) { for n := 20; n < 31; n++ { f := Factorial(uint64(n)) t.Logf("Factorial(%d) is %d", n, f) } } func TestBinomialCoefficient(t *testing.T) { for _, tv := range []struct { n, k, bc uint64 }{ {n: 0, k: 0, bc: 1}, {n: 1, k: 0, bc: 1}, {n: 1, k: 1, bc: 1}, {n: 2, k: 0, bc: 1}, {n: 2, k: 1, bc: 2}, {n: 2, k: 2, bc: 1}, {n: 3, k: 0, bc: 1}, {n: 3, k: 1, bc: 3}, {n: 3, k: 2, bc: 3}, {n: 3, k: 3, bc: 1}, {n: 4, k: 0, bc: 1}, {n: 4, k: 1, bc: 4}, {n: 4, k: 2, bc: 6}, {n: 4, k: 3, bc: 4}, {n: 4, k: 4, bc: 1}, {n: 5, k: 0, bc: 1}, {n: 5, k: 1, bc: 5}, {n: 5, k: 2, bc: 10}, {n: 5, k: 3, bc: 10}, {n: 5, k: 4, bc: 5}, {n: 5, k: 5, bc: 1}, } { if bc := BinomialCoefficient(tv.n, tv.k); bc != tv.bc { t.Errorf("BinomialCoefficient(%d, %d) is %d, expected %d", tv.n, tv.k, bc, tv.bc) } } } Loading
numeric/numeric.go 0 → 100644 +67 −0 Original line number Diff line number Diff line package numeric // Factorial calculates n!. func Factorial(n uint64) uint64 { if n < uint64(len(facsSmall)) { return factorialSmall(n) } return factorialCalc(n) } // Helpers... var ( facsSmall = []struct { n uint64 f uint64 }{ {n: 0, f: 1}, {n: 1, f: 1}, {n: 2, f: 2}, {n: 3, f: 6}, {n: 4, f: 24}, {n: 5, f: 120}, {n: 6, f: 720}, {n: 7, f: 5040}, {n: 8, f: 40320}, {n: 9, f: 362880}, {n: 10, f: 3628800}, {n: 11, f: 39916800}, {n: 12, f: 479001600}, {n: 13, f: 6227020800}, {n: 14, f: 87178291200}, {n: 15, f: 1307674368000}, {n: 16, f: 20922789888000}, {n: 17, f: 355687428096000}, {n: 18, f: 6402373705728000}, {n: 19, f: 121645100408832000}, {n: 20, f: 2432902008176640000}, //{n: 21, f: 51090942171709440000}, } ) func factorialSmall(n uint64) uint64 { if n < uint64(len(facsSmall)) { return facsSmall[int(n)].f } return 0 } func factorialCalc(n uint64) uint64 { var f uint64 = 1 for n > 1 { f *= n n-- } return f } // BinomialCoefficient calculates n over k. func BinomialCoefficient(n, k uint64) uint64 { if k == 0 { return 1 } if n == k { return 1 } return Factorial(n) / (Factorial(k) * Factorial(n-k)) }
numeric/numeric_test.go 0 → 100644 +78 −0 Original line number Diff line number Diff line package numeric import ( "testing" ) func TestFactorial(t *testing.T) { for _, tv := range []struct { n uint64 f uint64 }{ {n: 0, f: 1}, {n: 1, f: 1}, {n: 2, f: 2}, {n: 3, f: 6}, {n: 4, f: 24}, {n: 5, f: 120}, {n: 6, f: 720}, {n: 7, f: 5040}, {n: 8, f: 40320}, {n: 9, f: 362880}, {n: 10, f: 3628800}, {n: 11, f: 39916800}, {n: 12, f: 479001600}, {n: 13, f: 6227020800}, {n: 14, f: 87178291200}, {n: 15, f: 1307674368000}, {n: 16, f: 20922789888000}, {n: 17, f: 355687428096000}, {n: 18, f: 6402373705728000}, {n: 19, f: 121645100408832000}, {n: 20, f: 2432902008176640000}, //{n: 21, f: 51090942171709440000}, } { if f := Factorial(tv.n); f != tv.f { t.Errorf("Factorial(%d) is %d, expected %d", tv.n, f, tv.f) } } } func TestFactorial2(t *testing.T) { for n := 20; n < 31; n++ { f := Factorial(uint64(n)) t.Logf("Factorial(%d) is %d", n, f) } } func TestBinomialCoefficient(t *testing.T) { for _, tv := range []struct { n, k, bc uint64 }{ {n: 0, k: 0, bc: 1}, {n: 1, k: 0, bc: 1}, {n: 1, k: 1, bc: 1}, {n: 2, k: 0, bc: 1}, {n: 2, k: 1, bc: 2}, {n: 2, k: 2, bc: 1}, {n: 3, k: 0, bc: 1}, {n: 3, k: 1, bc: 3}, {n: 3, k: 2, bc: 3}, {n: 3, k: 3, bc: 1}, {n: 4, k: 0, bc: 1}, {n: 4, k: 1, bc: 4}, {n: 4, k: 2, bc: 6}, {n: 4, k: 3, bc: 4}, {n: 4, k: 4, bc: 1}, {n: 5, k: 0, bc: 1}, {n: 5, k: 1, bc: 5}, {n: 5, k: 2, bc: 10}, {n: 5, k: 3, bc: 10}, {n: 5, k: 4, bc: 5}, {n: 5, k: 5, bc: 1}, } { if bc := BinomialCoefficient(tv.n, tv.k); bc != tv.bc { t.Errorf("BinomialCoefficient(%d, %d) is %d, expected %d", tv.n, tv.k, bc, tv.bc) } } }