求999的阶乘!!!!

解决方案 »

  1.   

    你拿BigInteger做吧,int和long估计都不够用。利用迭代求,很简单。主要是别越界!
      

  2.   


    protected static ArrayList<BigInteger> list = new ArrayList<BigInteger>();
    static {
    list.add(BigInteger.valueOf(1));
    }
    public static BigInteger factorial(int x) {
    for (int size = list.size(); size <= x; size++) {
    BigInteger lastfact = (BigInteger) list.get(size - 1);
    BigInteger nextfact = lastfact.multiply(BigInteger.valueOf(size));
    list.add(nextfact);
    }
    return (BigInteger)list.get(x);
    } public static void main(String[] args) { System.out.println(999 + "!=" + factorial(6));
    }
      

  3.   

            System.out.println(999 + "!=" + factorial(6));
    换成999,我测试了下OK的
      

  4.   

    public final class Factorial { /**
     * Default thread count(CPU count * 4)
     */
    static final int THREAD_COUNT;
    static {
    THREAD_COUNT = Runtime.getRuntime().availableProcessors() << 2;
    } /**
     * Never instantiate this class.
     */
    private Factorial() {
    } /**
     * Calculates the factorial of n. A new thread pool will be initialized to
     * perform the calculation task, and destroyed thereafter.
     * 
     * @param n
     *            the value of n
     * @return the factorial of the given n
     * @throws Exception
     *             if exception occurs
     */
    public static final BigInteger factorial(final int n) throws Exception {
    ExecutorService threadPool = Executors.newFixedThreadPool(THREAD_COUNT);
    try {
    return factorial(n, threadPool, THREAD_COUNT);
    } finally {
    threadPool.shutdown();
    }
    } /**
     * Calculates the factorial of n. A specified thread pool will be used to
     * perform the calculation task, and will not be automatically destroyed.
     * 
     * @param n
     *            the value of n
     * @param threadPool
     *            the given thread pool to perform the calculation task
     * @param threadCount
     *            the number of threads to perform the calculation task
     * @return the factorial of the given n
     * @throws Exception
     *             if exception occurs
     */
    public static BigInteger factorial(final int n, ExecutorService threadPool, final int threadCount) throws Exception { List<Callable<BigInteger>> tasks = new ArrayList<Callable<BigInteger>>(threadCount);
    for (int i = 1; i <= threadCount; i++) {
    final int threadNo = i;
    Callable<BigInteger> worker = new Callable<BigInteger>() { @Override
    public BigInteger call() throws Exception {
    BigInteger result = BigInteger.ONE;
    for (int x = threadNo; x <= n; x += threadCount) {
    result = BigInteger.valueOf(x).multiply(result);
    }
    return result;
    } };
    tasks.add(worker);
    } BigInteger result = BigInteger.ONE;
    List<Future<BigInteger>> futureList = threadPool.invokeAll(tasks);
    for (Future<BigInteger> future : futureList) {
    result = future.get().multiply(result);
    }
    return result;
    }
    }402387260077.... 耗时15ms这段代码算999!可能大材小用了,不过,如果计算99999!就体现出优势了。在我的电脑上99999!在20秒左右。分线程计算的原因,在以前一个C#讨论99999!的帖子里,我回复过。可以搜一下。
      

  5.   

    楼上用到了缓存的思路,不过我想过,实际应用中可能帮不了大忙。这个与sieve法算素数,把first N primes放到一个数组里面,还是不一样的。
      

  6.   

    int multiply = 1;
    for(int i = 1; i<1000; i++ ){
       multiply*i 
    }
    return multiply;
      

  7.   

    而且,如果缓存每个结果,如果数字大了,绝对OutOfMemory
    15ms不是15s,9999的时候,我快半秒,99999的时候,比你快40多秒。
      

  8.   

    import java.math.BigInteger;public class Test {    public static void main(String args[]) {
            BigInteger bi = factorial(999);
            System.out.println(bi);
        }
        
        public static BigInteger factorial(int n) {
            if(n < 2) {
                return BigInteger.ONE;
            }
            int[] oddCount = new int[Integer.numberOfTrailingZeros(Integer.highestOneBit(n))];
            int shift = init(oddCount, n);
            BigInteger result = BigInteger.ONE;
            BigInteger bg = BigInteger.ONE;
            BigInteger tmp = BigInteger.ONE;        int max = oddCount[oddCount.length - 1];
            int offset = (oddCount[0] + 1) & 1;
            int oddStart = 1;
            while(oddStart <= max) {
                tmp = tmp.multiply(new BigInteger(String.valueOf(2 * oddStart + 1)));
                if(oddCount[offset] == oddStart) {
                    offset++;
                    bg = bg.multiply(tmp);
                    tmp = BigInteger.ONE;
                    result = result.multiply(bg);
                }
                oddStart++;
            }
            return result.shiftLeft(shift);
        }
    }算 99999! 的话需要 15~16s,但是要输出结果就很耗时。
      

  9.   

    少贴了个方法    private static int init(int[] oddCount, int n) {
            int s = n;
            int r = 0;
            int k = oddCount.length;
            while(k > 0) {
                s >>= 1;
                oddCount[--k] = n - s - 1; 
                n = s;
                r += s;
            }
            return r;
        }
      

  10.   

    shine333的算法是比较好的,用了多线程以及线程池的优势。
    在性能和稳定性上,值得借鉴。
    学习了。
      

  11.   


    他只贴了方法而没有写main函数,你自己写个main函数测试一下就可以了
      

  12.   

    在 19 楼贴的那个是原来在一个页面上看到的算法,那个页面我一下子找不到了,具体的思路就是将阶乘中所有的“2”提出来,仅将奇数相乘(像下式中的 1 * 3 * 5 只要计算一次就可以了,下一次再乘以 7…… 什么的。),以减少乘法次数,最后使用左移位将“2”补回去。具体的阶乘分解,我用 Latex 编辑器弄了个公式:
      

  13.   

    Latex 公式太长了,直接点链接吧:[url=http://latex.codecogs.com/gif.latex?\100dpi%20\begin{align*}%20&1*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16*17*18*19*20\\=&1*3*5*7*9*11*13*15*17*19*%282*4*6*8*10*12*14*16*18*20%29\\=&1*3*5*7*9*11*13*15*17*19*[%281*3*5*7*9%29*%282^5%29*%284*8*12*16*20%29]\\=&1*3*5*7*9*11*13*15*17*19*[%281*3*5*7*9%29*%282^5%29*%281*3*5%29*%282^6%29*8*16]\\=&%281*3*5*7*9*11*13*15*17*19%29*%281*3*5*7*9%29*%281*3*5%29*%282^5%29*%284^3%29*8*16\\=&%281*3*5*7*9*11*13*15*17*19%29*%281*3*5*7*9%29*%281*3*5%29*%282^5%29*%282^6%29*%282^3%29*%282^4%29\\=&%281*3*5*7*9*11*13*15*17*19%29*%281*3*5*7*9%29*%281*3*5%29*%282^{18}%29%20\end{align*}]http://latex.codecogs.com/gif.latex?\100dpi%20\begin{align*}%20&1*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16*17*18*19*20\\=&1*3*5*7*9*11*13*15*17*19*%282*4*6*8*10*12*14*16*18*20%29\\=&1*3*5*7*9*11*13*15*17*19*[%281*3*5*7*9%29*%282^5%29*%284*8*12*16*20%29]\\=&1*3*5*7*9*11*13*15*17*19*[%281*3*5*7*9%29*%282^5%29*%281*3*5%29*%282^6%29*8*16]\\=&%281*3*5*7*9*11*13*15*17*19%29*%281*3*5*7*9%29*%281*3*5%29*%282^5%29*%284^3%29*8*16\\=&%281*3*5*7*9*11*13*15*17*19%29*%281*3*5*7*9%29*%281*3*5%29*%282^5%29*%282^6%29*%282^3%29*%282^4%29\\=&%281*3*5*7*9*11*13*15*17*19%29*%281*3*5*7*9%29*%281*3*5%29*%282^{18}%29%20\end{align*}[/url]
      

  14.   

    受不了[url=http://latex.codecogs.com/gif.latex?\100dpi%20\begin{align*}%20&1*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16*17*18*19*20\\=&1*3*5*7*9*11*13*15*17*19*%282*4*6*8*10*12*14*16*18*20%29\\=&1*3*5*7*9*11*13*15*17*19*[%281*3*5*7*9%29*%282^5%29*%284*8*12*16*20%29]\\=&1*3*5*7*9*11*13*15*17*19*[%281*3*5*7*9%29*%282^5%29*%281*3*5%29*%282^6%29*8*16]\\=&%281*3*5*7*9*11*13*15*17*19%29*%281*3*5*7*9%29*%281*3*5%29*%282^5%29*%284^3%29*8*16\\=&%281*3*5*7*9*11*13*15*17*19%29*%281*3*5*7*9%29*%281*3*5%29*%282^5%29*%282^6%29*%282^3%29*%282^4%29\\=&%281*3*5*7*9*11*13*15*17*19%29*%281*3*5*7*9%29*%281*3*5%29*%282^{18}%29%20\end{align*}]http://latex.codecogs.com/gif.latex?\100dpi%20\begin{align*}%20&1*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16*17*18*19*20\\=&1*3*5*7*9*11*13*15*17*19*%282*4*6*8*10*12*14*16*18*20%29\\=&1*3*5*7*9*11*13*15*17*19*[%281*3*5*7*9%29*%282^5%29*%284*8*12*16*20%29]\\=&1*3*5*7*9*11*13*15*17*19*[%281*3*5*7*9%29*%282^5%29*%281*3*5%29*%282^6%29*8*16]\\=&%281*3*5*7*9*11*13*15*17*19%29*%281*3*5*7*9%29*%281*3*5%29*%282^5%29*%284^3%29*8*16\\=&%281*3*5*7*9*11*13*15*17*19%29*%281*3*5*7*9%29*%281*3*5%29*%282^5%29*%282^6%29*%282^3%29*%282^4%29\\=&%281*3*5*7*9*11*13*15*17*19%29*%281*3*5*7*9%29*%281*3*5%29*%282^{18}%29%20\end{align*}[/url]
      

  15.   

    URL 地址太长了:http://latex.codecogs.com/gif.latex?\100dpi%20\begin{align*}%20&1*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16*17*18*19*20\\=&1*3*5*7*9*11*13*15*17*19*%282*4*6*8*10*12*14*16*18*20%29\\=&1*3*5*7*9*11*13*15*17*19*[%281*3*5*7*9%29*%282^5%29*%284*8*12*16*20%29]\\=&1*3*5*7*9*11*13*15*17*19*[%281*3*5*7*9%29*%282^5%29*%281*3*5%29*%282^6%29*8*16]\\=&%281*3*5*7*9*11*13*15*17*19%29*%281*3*5*7*9%29*%281*3*5%29*%282^5%29*%284^3%29*8*16\\=&%281*3*5*7*9*11*13*15*17*19%29*%281*3*5*7*9%29*%281*3*5%29*%282^5%29*%282^6%29*%282^3%29*%282^4%29\\=&%281*3*5*7*9*11*13*15*17*19%29*%281*3*5*7*9%29*%281*3*5%29*%282^{18}%29%20\end{align*}
      

  16.   

    BigInteger?想不到java还有这个类,我记得在C#中,曾见过一个用string表示的数字的一个类,不是不是C#本身提供的,是需要自己写出来的。想不到java中竟然已经自带,呵呵
      

  17.   

    9楼的我改了下, 不要用list用list会OutOfMemory
    速度没有火龙果的快, 但是写起来简单..
    package com.lzw;import java.math.BigInteger;public class Factorial
    {
        private static BigInteger temp = BigInteger.ONE;
        
        private static BigInteger count = BigInteger.ONE;
        
        public static BigInteger factorial(int num)
        {
            for (int i = 1; i <= num; i++)
            {
                   temp = temp.multiply(count);
                   count = count.add(BigInteger.ONE);
            }
            return null;
        }
        public static void main(String[] args)
        {
          long start = System.currentTimeMillis();
          BigInteger bi = factorial(99999);
          long end = System.currentTimeMillis();
          System.out.println(end-start);
        }
    }
      

  18.   

    用递归吧
    可以实现你要的
    private int JC(int Number)
    (
        if(number==1)
        {
            return 1;
        }
        return Number * JC(Number-1);
    )
      

  19.   

    递归的话也要用BigInteger,int肯定不够的
    而且递归的话次数高会出现栈溢出……
      

  20.   


    问个低级问题,这里的return 1;执行 之后,为什么return Number * JC(Number-1);还执行
    不是直接return回去?
      

  21.   

    return 1是递归的最终条件。
      

  22.   

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    int main()
    {
        int buffer[500];
        memset(buffer,0,sizeof(buffer));
        int p ;
        printf("输入整数:");
        scanf("%d",&p);
        bool flag = false;
        bool flag1[500]={false};
        int add = 0;
        memcpy(buffer+499,&p,sizeof(p));
        for(int m=p-1;m>=1;--m)
        {
        for(int i=sizeof(buffer)/sizeof(int)-1;i>=0;--i)
        {
            if(flag)
            {
            buffer[i]= buffer[i]*m+add;
            flag  = false ;
            add =  0;
            }
            else
            {
              buffer[i]= buffer[i]*m ;
            }
            if(buffer[i]>9)
            {
              add = buffer[i]/10;
              buffer[i] = buffer[i]%10;
              if(buffer[i]==0)
              {
                flag1[i] = true ;
              }
              flag = true ;
            }
        }
        }
        printf("%d!的阶乘为",p);
        for(int j=0;j<=sizeof(buffer)/sizeof(int)-1;j++)
        {
            if(flag1[j]||buffer[j]!=0)
            {
             printf("%d",buffer[j]);
            }
        }
        printf("\n");
        return 0;
    }
      

  23.   

    其实,如果不需要得到结果的每一位的话,可以利用对数的性质来求解。如求n的阶乘,则可用如下公式:n!=10^(log 10(n!))=10^(log 10(1)+log 10(2)+log 10(3)+……+log 10(n)),其中,log 10(n)表示以10为底,n的对数。这样的话,就能求超大的阶乘了,当然,这种方法只在对结果要求不高时适用...
      

  24.   

    (define (f n)
      (if (= n 1)
          1
          (* n(f (- n 1)))))
      

  25.   

    能不能用Gamma函数的数值算法算一个近似值出来?