zoukankan      html  css  js  c++  java
  • 算法题007 计算n的阶乘

    阶乘的计算

    阶乘的定义

      n! = n * (n - 1) * (n - 2) * ... * 3 * 2 * 1

     

    简单的程序代码(可以算较小的阶乘)

      没有考虑变量表达范围,假设所得结果用long型表示。

      这里需要注意的是0的阶乘应该是1.

    n较小的阶乘算法
    #include <iostream>
    using namespace std;
    
    int main(int argc, char* argv[])
    {
        int n = 0;
        long result = 0;
    
        while( cin >> n)
        {
            if(n > 0)
            {
                result = n;
                while(n > 1)
                {
                    result *= (n-1);
                    --n;
                }
            }
            else if (n == 0)
            {
                result = 1;
            }
    
            cout << result << endl;
        }
    
        return 0;
    }

     

      这个程序的主要问题就是long的选取,long型是4个字节,32位,因为是带符号的,能表示的范围最大不超过2的31次方,即不超过10的10次方。

      即long型可以表示的数肯定是十进制下的10位数之内的。

      而14的阶乘就已经是一个11位数了。

      (事实上13的阶乘就已经超过了long的表示范围,因为13的阶乘的最高位是6,而2的31次方最高位是2。)

      所以这个程序只能计算12以下的数的阶乘。

      考虑过将数据类型进一步改为long double,得到的结果是科学计数法显示的,只有有限的有效数字,精度不高,并且当n进一步增大再次超过表示范围的时候呢?所以还是需要另外的处理办法。

     

     

    大数阶乘运算  

      当n大于等于20时,因为运算结果超出了long型的表示范围,所以必须采取大数字的一般处理方法:用数组表示。

      程序如下,自己写的,没有仔细研究文后的参考资料。 

    大数阶乘运算
    #include <iostream>
    using namespace std;
    
    
    
    int main(int argc, char* argv[])
    {
        int n = 0;
        int number[21] = {0};
        int bitCount = 0;//记录所用到的位数下标
    
        while( cin >> n)
        {
            bitCount = 0;
            if(n > 0)
            {
                //先把n用数组表示,0号元素为个位
                int copyOfN = n;
    
                for(int i = 0; copyOfN > 0; copyOfN/=10, ++i)
                {
                    number[i] = copyOfN % 10;
                    bitCount = i;
    
                    //cout << "number: " << number[i] << endl;
                    //cout << "bitCount: "<<bitCount <<endl;
                }
    
                //然后进行阶乘运算
    
                while( --n > 0)
                {
                    int carry = 0;
                    for(int i = 0; i<= bitCount; ++i)
                    {
                        int temp = number[i] * n + carry;
    
                        number[i] = temp % 10;
                        carry = temp / 10;
    
                    }
                    while(carry > 0)
                    {
                        //如果有多余的进位,则说明数组需要添加位数
                        //注意,这里由于把第二个乘数当做整体处理,而不是一位一位处理,所以进位可能也不只是一位
                        number[++ bitCount] = carry % 10;
                        carry /= 10;
                    }
                    
                }
    
    
                //最后输出运算结果
                for(int i = bitCount; i >= 0; --i)
                {
                    cout << number[i];
                }
                cout << endl;
            }
            else if (n == 0)
            {
                cout << 1 << endl;
            }
            else
            {
                cout << "负数没有阶乘!" << endl;
            }
    
    
    
        }
    
    
        return 0;
    }

      还是需要细心一些的。

      主要检查循环变量是否更新,对于进位的理解是否正确等。

      结果用计算器验证过,并且在九度上提交通过:http://ac.jobdu.com/problem.php?pid=1067

     

    其他参考资料

      大数运算(采用数组模拟):

    http://www.cnblogs.com/dolphin0520/archive/2011/07/16/2108006.html

    http://www.cnblogs.com/yuzhaoxin/archive/2011/11/19/2205221.html

    http://confach.cnblogs.com/archive/2005/07/14/192703.html

    http://www.cnblogs.com/lsx54321/archive/2012/07/20/2601618.html

    http://www.cnblogs.com/phinecos/archive/2009/10/06/1578411.html

     

  • 相关阅读:
    使用Random类生成指定范围的随机数
    js ==和===的区别
    js中的undefined
    js的split函数
    springboot发送邮件
    1032 Sharing (25分)(数组链表)
    1031 Hello World for U (20分)
    1030 Travel Plan (30分)(dijkstra 具有多种决定因素)
    1029 Median (25分)
    1026 Table Tennis (30分)
  • 原文地址:https://www.cnblogs.com/mengdd/p/2960684.html
Copyright © 2011-2022 走看看