大数的阶乘
众所周知,阶乘的定义就是n! = (n-1)!*n,但是有基本的初始条件的,即0! = 1
因此1! = 1*0! = 1 * 1 = 1;
2! = 2*1! = 2 * 1 = 2;
依次类推,但是当n足够大时,整型根本无法装下n的阶乘,如果用C语言来实现的话,根本不可能,那怎么办呢?
其实阶乘也无非是乘法和加法罢了,如4!= 24;我们可以用数组来存各位,结舌数组的起始长度是1哈,每当遇到超过长度时,就自加1,不过这里要稍微处理下的,我们可以倒过来存,以便做乘法的,可以这样来存。
4! 4 2
5! = 5 * 4!,可以用5去乘以4,如果大于10则需向高位进位,下一位的结果就等于下一位乘以5然后加上刚才的进位,当然也要取余数哈,然后继续看有没进位哈,知道遍乘数组每一位哈。
给个能求1000!的例子,用C语言实现的,供大家参考,以便交流学习哈。
#include <iostream>
using namespace std;
#define N 1000 // 所需求的N的阶乘
static int a[N*3]; // 保存阶乘的各位
int main()
{
int i,j; //临时变量
int len = 1;
int tem,carry;
a[1] = 1; //1的阶乘
for (i = 2;i<=N;i++) //求阶乘的方法
{
carry = 0;
for (j=1;j<=len;j++)
{
tem = a[j]*i +carry;
a[j] = tem%10;
carry = tem/10;
if (j==len&&carry!=0)
{
len++;
}
}
}
for (i = len;i>=1;i--) //输出各位
{
cout<<a[i];
}
cout<<endl;
return 0;
}
我们也可以用Python来实现的哈,很简单两句话,就好啦
Import math
Math.factorial(1000)就OK了,爽把!不过3.x以上的版本才有此函数哈。
JAVA
public class Factorial {
public static void main(String[] args) {
long start =System.currentTimeMillis();
int i = 10000;
BigInteger big = new BigInteger(Integer.toString(i));
for (int j = i - 1; j > 1; j--) {
big = big.multiply(new BigInteger(Integer.toString(j)));
}
long end = System.currentTimeMillis();
System.out.println("run time: "+(end-start)+"ms");
System.out.println(big.toString());
System.out.println("show time: "+(System.currentTimeMillis()-end)+"ms");
}
}
C#
10进制--> 1,000,000,000 进制
1000!阶乘0.048s 48ms (包含输出,以及每1000输出一次)
10000!阶乘5.553125s 5531.25ms (包含输出,以及每1000输出一次)
代码如下:
C# code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace Factorial
{
class Program
{
static void Main(string[] args)
{
int Number = 0;
//接收输入
Console.WriteLine(@"Please input a numeric:");
Number = int.Parse(Console.ReadLine().Trim());
DateTime BeginTime = DateTime.Now;
DateTime EndTime = DateTime.Now;
//阶乘计算
FactorialWithBaseNumberAndList.FactorialCalculation(Number);
EndTime = DateTime.Now;
Console.WriteLine(EndTime.Subtract(BeginTime).TotalMilliseconds + " ms!");
Console.ReadKey();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Factorial
{
class FactorialWithBaseNumberAndList
{
public const ulong baseNumber = 1000000000;
public static List<ulong> GetProduct(List<ulong> FactorX, List<ulong> FactorY)
{
List<ulong> ret = new List<ulong>();
ulong Carry = 0; //进位数
ulong Product = 0; //乘积
int Position = 0; //位数
ulong Number = 0; //乘积 % baseNumber 取余的余数
ulong TempNumber = 0; //旧值
//循环历遍因数X中的元素
for (int i = 0; i < FactorX.Count; i++)
{
//清除进位数
Carry = 0;
//循环历遍因数Y中的元素
for (int j = 0; j < FactorY.Count; j++)
{
//取得乘积,例如 9 * 9 = 81
Product = FactorX[i] * FactorY[j];
//取得位数,例如 因数X的第1位 * 因数Y的第1位,那么其乘积所在开始的位数则为2,
//比如 20 * 30 中两个十位数相乘其结果
//开始的位数为(2所在位数为1 + 3所在位数为1) = 6所在位数为2,即是600
Position = i + j;
//取得乘积 % baseNumber 取余的余数
Number = Product % baseNumber;
//判断乘积结果中该位是否有值,有值则相加,否则插入
if (ret.Count > Position)
{
//临时存放旧值
TempNumber = ret[Position];
//更新当前位的值,当前位值 = (旧值 + 取得乘积 % baseNumber 取余的余数 + 上一次进位数) % baseNumber 取余
ret[Position] = (TempNumber + Number + Carry) % baseNumber;
//取得当前进位值,當前進位值 = (旧值 + 乘积 + 进位)/baseNumber 取整
Carry = (ulong)Math.Floor((TempNumber + Product + Carry) / baseNumber * 1.0);
}
else
{
//插入位数,值
ret.Add((Number + Carry) % baseNumber);
//取得当前进位值,當前進位值 = (乘积 + 进位)/10 取整
Carry = (ulong)Math.Floor((Product + Carry) / baseNumber * 1.0);
}
}
//当最后进位数不为0时,需要新增最高位,其值为进位数
if (Carry != 0) ret.Add(Carry);
}
return ret;
}
/// <summary>
/// 阶乘计算
/// </summary>
public static void FactorialCalculation(int Number)
{
List<ulong> ProductZ = new List<ulong>(); //乘积Z - Dictionary
List<ulong> FactorX = new List<ulong>(); //因数X - Dictionary
//初始化乘积,避免出错
ProductZ.Add(1);
//阶乘数历遍,从1开始
for (int i = 1; i <= Number; i++)
{
//清空因数
FactorX.Clear();
//每1000个数输出一次
if (i % 1000 == 0) Console.WriteLine(i.ToString());
FactorX.Add(Convert.ToUInt64(i));
//计算乘积,将上一次的结果作为因数Y传入
ProductZ = GetProduct(FactorX, ProductZ);
}
//显示结果
ShowResult(ProductZ);
}
/// <summary>
/// 显示结果
/// </summary>
/// <param name="Product">乘积 - List </param>
/// <param name="DecimalDigits">小数位数 - int</param>
public static void ShowResult(List<ulong> Product)
{
StringBuilder sb = new StringBuilder();
for (int i = Product.Count - 1; i >= 0; i--)
{
sb.Append(Product[i]);
}
Console.WriteLine("Result:" + sb.ToString());
}
}
}
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/Lost_Painting/archive/2010/02/09/5302815.aspx
//-----------------------------------------------------------------------------
//
// 算法:阶乘类
//
// 版权所有(C) Snowdust
// 个人博客 http://blog.csdn.net/snwodust & http://snowdust.cnblogs.com
// MSN & Email snwodust77@sina.com
//
// 此源代码可免费用于各类软件(含商业软件)
// 允许对此代码的进一步修改与开发
// 但必须完整保留此版权信息
//
// 调用方法如下:
// int num = 10000;
// Arithmetic.Factorial f = new Arithmetic.Factorial(num);
// List<int> result = f.Calculate();
// String ret = f.ToString();
// 返回结果:result为100000进制表示的范型,ret为转换成十制制的字符串
//
// 版本历史:
// V0.1 2010-03-17 摘要:首次创建
//
//-----------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Text;
namespace Arithmetic
{
public class Factorial
{
#region 定义属性
/// <summary>
/// 进制
/// </summary>
private int m_BaseNumber = 100000;
public int BaseNumber
{
get
{
return m_BaseNumber;
}
}
/// <summary>
/// 待求阶乘的数
/// </summary>
private int m_Number;
/// <summary>
/// 结果
/// </summary>
private List<int> m_Result = new List<int>();
#endregion
#region 构造函数
/// <summary>
/// 构造函数
/// </summary>
/// <param name="n">待求阶乘的数</param>
public Factorial(int n)
{
m_Number = n;
m_Result = new List<int>();
}
#endregion
#region 方法
/// <summary>
/// 计算阶乘
/// </summary>
/// <returns>结果范型</returns>
public List<int> Calculate()
{
int digit = (int)System.Math.Log10(m_BaseNumber);
int len = (int)(m_Number * System.Math.Log10((m_Number + 1) / 2)) / digit;//计算n!有数数字的个数
len += 2; //保险起见,加长2位
int[] a = new int[len];
int i, j;
long c;
int m = 0;
a[0] = 1;
for (i = 2; i <= m_Number; i++)
{
c = 0;
for (j = 0; j <= m; j++)
{
long t = a[j] * i + c;
c = t / m_BaseNumber;
a[j] = (int)(t % m_BaseNumber);
}
while (c > 0)
{
m++;
a[m] = (int)(c % m_BaseNumber);
c = c / m_BaseNumber;
}
}
for (i = 0; i <= m; i++)
{
m_Result.Add(a[i]);
}
return m_Result;
}
/// <summary>
/// 重写ToString方法
/// </summary>
/// <returns>结果字符串</returns>
public override string ToString()
{
if (m_Result.Count == 0)
{
Calculate();
}
StringBuilder sb = new StringBuilder();
int digit = (int)System.Math.Log10(m_BaseNumber);
sb.Append(m_Result[m_Result.Count - 1]);
for (int i = m_Result.Count - 2; i >= 0; i--)
{
sb.Append(m_Result[i].ToString().PadLeft(digit, '0'));
}
return sb.ToString();
}
#endregion
}
}
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/Snowdust/archive/2010/03/18/5392444.aspx
C
#include<stdio.h>
#include<conio.h>
int arr[1000000]={0};
void mul(int arr[],int n,int *len)
{
int c=0,i,l=*len;
for(i=0;i<l;i++)
{
arr[i]=arr[i]*n+c;
c=arr[i]/10;
arr[i]%=10;
}
while(c!=0)
{
arr[l++]=c%10;
c/=10;
}
*len=l;
}
int main()
{
int i,n,len;
scanf("%d",&n);
len=1;arr[0]=1;
for(i=2;i<=n;i++)
mul(arr,i,&len);
for(i=len-1;i>=0;i--)
printf("%d",arr[i]);
printf("/n");
getch();
return 0;
}
C++
写的一个C++实现10000的阶乘的代码
#include<iostream>
#define N 10000//设阶乘数为10000
#define SIZE 40000//预留40000位保存结果
using namespace std;
void mul(int *n1,int n2)//两数相乘
{
for(int i=0;i!=SIZE;++i)
n1[i]*=n2;
for(int i=0;i!=SIZE;++i){
n1[i+1]+=(n1[i]/10);
n1[i]%=10;
}
}
int main()
{
int *num=new int[SIZE];
memset(num,0,SIZE);
num[0]=1;
//N的阶乘
for(int i=1;i!=N+1;++i){
mul(num,i);
}
//输出时排除开头的0
for(int i=SIZE-1;i!=-1;--i){
if(0!=num[i]){
for(int j=i;j!=-1;--j){
cout <<num[j];
}
break;
}
}
delete[] num;
return 0;
}