1: // The Poor Man's Implementation of the factorial.
2: // All math is on board, no additional libraries
3: // are needed. Good enough to compute the factorial
4: // up to n=10000 in a few seconds.
5:
6: namespace Luschny.Math.Factorial
7: {
8: public class FactorialPoorMans
9: {
10: public FactorialPoorMans() { }
11:
12: private long N;
13:
14: public string Factorial(int n)
15: {
16: if (n < 0)
17: {
18: throw new System.ArgumentException(
19: ": n >= 0 required, but was " + n);
20: }
21:
22: if (n < 2) return "1";
23:
24: var p = new DecInteger(1);
25: var r = new DecInteger(1);
26:
27: N = 1;
28:
29: int h = 0, shift = 0, high = 1;
30: int log2n = (int)System.Math.Floor(System.Math.Log(n) * 1.4426950408889634);
31:
32: while (h != n)
33: {
34: shift += h;
35: h = n >> log2n--;
36: int len = high;
37: high = (h - 1) | 1;
38: len = (high - len) / 2;
39:
40: if (len > 0)
41: {
42: p = p * Product(len);
43: r = r * p;
44: }
45: }
46:
47: r = r * DecInteger.Pow2(shift);
48: return r.ToString();
49: }
50:
51: private DecInteger Product(int n)
52: {
53: int m = n / 2;
54: if (m == 0) return new DecInteger(N += 2);
55: if (n == 2) return new DecInteger((N += 2) * (N += 2));
56: return Product(n - m) * Product(m);
57: }
58: } // endOfFactorialPoorMans
59:
60: internal class DecInteger
61: {
62: private const long mod = 100000000L;
63: private int[] digits;
64: private int digitsLength;
65:
66: public DecInteger(long value)
67: {
68: digits = new int[] { (int)value, (int)(value >> 32) };
69: digitsLength = 2;
70: }
71:
72: private DecInteger(int[] digits, int length)
73: {
74: this.digits = digits;
75: digitsLength = length;
76: }
77:
78: public static DecInteger Pow2(int e)
79: {
80: if (e < 31) return new DecInteger((int)System.Math.Pow(2, e));
81: return Pow2(e / 2) * Pow2(e - e / 2);
82: }
83:
84: public static DecInteger operator *(DecInteger a, DecInteger b)
85: {
86: int alen = a.digitsLength, blen = b.digitsLength;
87: int clen = alen + blen + 1;
88: int[] digits = new int[clen];
89:
90: for (int i = 0; i < alen; i++)
91: {
92: long temp = 0;
93: for (int j = 0; j < blen; j++)
94: {
95: temp = temp + ((long)a.digits[i] * (long)b.digits[j]) + digits[i + j];
96: digits[i + j] = (int)(temp % mod);
97: temp = temp / mod;
98: }
99: digits[i + blen] = (int)temp;
100: }
101:
102: int k = clen - 1;
103: while (digits[k] == 0) k--;
104:
105: return new DecInteger(digits, k + 1);
106: }
107:
108: public override string ToString()
109: {
110: var sb = new System.Text.StringBuilder(digitsLength * 10);
111: sb = sb.Append(digits[digitsLength - 1]);
112: for (int j = digitsLength - 2; j >= 0; j--)
113: {
114: sb = sb.Append((digits[j] + (int)mod).ToString().Substring(1));
115: }
116: return sb.ToString();
117: }
118: }
119: }
120:
121: // public static void Main (string[] arguments)
122: // {
123: // int n = 1000;
124: // if (arguments.Length != 0)
125: // {
126: // n = System.Convert.ToInt32(arguments[0]);
127: // }
128: // else
129: // {
130: // System.Console.WriteLine("Please give an argument!");
131: // }
132: // FactorialPoorMans f = new FactorialPoorMans();
133: // System.Console.WriteLine(n + "! = " + f.Factorial(n));
134: // System.Console.ReadLine();
135: // }