算法题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

 

posted @ 2013-03-15 02:06  圣骑士wind  阅读(3897)  评论(0编辑  收藏  举报