⑴ 誰能告訴一下階乘的具體計算步驟,時間長了,都忘了
在《大數階乘之計算從入門到精通-大數的表示》中,我們學習了如何表示和存儲一個大數。在這篇文章中,我們將討論如何對大數做乘法運算,並給出一個可以求出一個大整數階乘的所有有效數字的程序。
大整數的存儲和表示已經在上一篇文章做了詳細的介紹。其中最簡單的表示法是:大數用一個字元型數組來表示,數組的每一個元素表示一位十進制數字,高位在前,低位在後。那麼,用這種表示法,如何做乘法運算呢?其實這個問題並不困難,可以使用模擬手算的方法來實現。回憶一下我們在小學時,是如何做一位數乘以多位數的乘法運算的。例如:2234*8。
我們將被乘數表示為一個數組A[], a[1],a[2],a[3],a[4]分別為2,2,3,4,a[0]置為0。
Step1: 從被乘數的個位a[4]起,取出一個數字4.
Step2: 與乘數8相乘,其積是兩位數32,其個位數2作為結果的個位,存入a[4], 十位數3存入進位c。
Step3: 取被乘數的上一位數字a[3]與乘數相乘,並加上上一步計算過程的進位C,得到27,將這個數的個位7作為結果的倒數第二位,存入a[3],十位數2存入進位c。
Step4:重復Step3,取a[i](i依次為4,3,2,1)與乘數相乘並加上c,其個位仍存入a[i],十位數字存入c,直到i等於1為止。
Step5:將最後一步的進位c作為積的最高位a[0]。
這一過程其實和小學學過的多位數乘以一位數的珠算乘法一模一樣,學過珠算乘法的朋友還有印象嗎?
在計算大數階乘的過程中,乘數一般不是一位數字,那麼如何計算呢?我們可以稍作變通,將上次的進位加上本次的積得到數P,將P除以10的余數做為結果的本位,將P除以10的商作為進位。當被乘數的所有數字都和乘數相乘完畢後,將進位C放在積的最前面即可。下面給出C語言代碼。
一個m位數乘以n位數,其結果為m+n-1,或者m+n位,所以需首先定義一個至少m+n個元素的數組,並置前n位為0。
計算一個m位的被乘數乘以一個n位的整數k,積仍存儲於數組a
[cpp] view plainprint?
01.void mul(unsigned char a[],unsigned long k,int m,int n)
02.{
03. int i;
04. unsigned long p;
05. unsigned long c=0;
06.
07. for ( i=m+n-1; i>=n;i--)
08. {
09. p= a[i] * k +c;
10. a[i]=(unsigned char)( p % 10);
11. c= p / 10;
12. }
13.
14. while (c>0)
15. {
16. a[i]=(unsigned char)( c % 10);
17. i--;
18. c /=10;
19. }
20.}
21.
22.int main(int argc, char* argv[])
23.{
24. int i;
25. unsigned char a[]={0,0,0,2,3,4,5};
26. mul(a,678,4,3);
27. i=0;
28. while ( a[i]==0)
29. i++;
30. for (;i<4+3;i++)
31. printf("%c",a[i]+』0』); //由於數a[i](0<=a[i] <=9)對應的可列印字任符為』0』到』9』,所以顯示為i+』0』
32. return 0;
33.}
void mul(unsigned char a[],unsigned long k,int m,int n)
{
int i;
unsigned long p;
unsigned long c=0;
for ( i=m+n-1; i>=n;i--)
{
p= a[i] * k +c;
a[i]=(unsigned char)( p % 10);
c= p / 10;
}
while (c>0)
{
a[i]=(unsigned char)( c % 10);
i--;
c /=10;
}
}
int main(int argc, char* argv[])
{
int i;
unsigned char a[]={0,0,0,2,3,4,5};
mul(a,678,4,3);
i=0;
while ( a[i]==0)
i++;
for (;i<4+3;i++)
printf("%c",a[i]+』0』); //由於數a[i](0<=a[i] <=9)對應的可列印字任符為』0』到』9』,所以顯示為i+』0』
return 0;
}
從上面的例子可知,在做乘法之前,必須為數組保留足夠的空間。具體到計算n!的階乘時,必須准備一個能容納的n!的所有位數的數組或者內存塊。即數組采有靜態分配或者動態分配。前者代碼簡潔,但只適應於n小於一個固定的值,後者靈活性強,只要有足夠的內存,可計算任意n的階乘,我們這里討論後一種情況,如何分配一塊大小合適的內存。
n!有多少位數呢?我們給出一個近似的上限值:n! <(n+1)/2的n次方,下面是推導過程。
Caes 1: n是奇數,則中間的那個數mid= (n+1)/2, 除了這個數外,我們可以將1到n之間的數分成n/2組,每組的兩個數為 mid-i和mid+i (i=1到mid-1),如1,2,3,4,5,6,7 可以分為數4,和3對數,它們是(3,5),(2,6)和(1,7),容易知道,每對數的積都於小mid*mid,故n!小於(n+1)/2 的n的次方。
Case 2: n 是個偶數,則中間的兩個數(n-1)/2和(n+1)/2, 我們將(n+1)/2記做mid,則其它的幾對數是(mid-2,mid+1),(mid-3)(mid+2)等等,容易看出,n!小於mid 的n次方。
由以上兩種情況可知,對於任意大於1的正整數n, n!<(n+1)/2的n次方。
如果想求出n!更准確的上限,可以使用司特林公式,參見該系列文章《階乘之計算從入門到精通-近似計算之二》。
到此,我們已經解決大數階乘之計算的主要難題,到了該寫出一個完整程序的時候了,下面給出一個完整的代碼。
[cpp] view plainprint?
01.#include "stdio.h"
02.#include "stdlib.h"
03.#include "memory.h"
04.#include "math.h"
05.#include "malloc.h"
06.
07.void calcFac(unsigned long n)
08.{
09. unsigned long i,j,head,tail;
10. int blkLen=(int)(n*log10((n+1)/2)); //計算n!有數數字的個數
11. blkLen+=4; //保險起見,多加4位
12.
13. if (n<=1)
14. { printf("%d!=0/n",n); return;}
15.
16. char *arr=(char *)malloc(blkLen);
17. if (arr==NULL)
18. { printf("alloc memory fail/n"); return ;}
19.
20. memset(arr,0,sizeof(char)*blkLen);
21. head=tail=blkLen-1;
22. arr[tail]=1;
23.
24. for (i=2;i<=n;i++)
25. {
26. unsigned long c=0;
27. for (j=tail;j>=head;j--)
28. {
29. unsigned long prod=arr[j] * i +c;
30. arr[j]=(char)( prod % 10);
31. c= prod / 10;
32. }
33. while (c>0)
34. {
35. head--;
36. arr[head]=(char)(c % 10);
37. c/=10;
38. }
39. }
40. printf("%d!=",n);
41. for (i=head;i<=tail;i++)
42. printf("%c",arr[i]+'0');
43. printf("/n");
44.
45. free(arr);
46.}
47.
48.void testCalcFac()
49.{
50. int n;
51. while (1)
52. {
53. printf("n=?");
54. scanf("%ld",&n);
55. if (n==0)
56. break;
57. calcFac(n);
58. }
59.}
60.
61.int main(int argc, char* argv[])
62.{
63. testCalcFac();
64. return 0;
65.}
⑵ 階乘怎麼算啊
如果要精確計算階乘,階乘沒有什麼簡便方法,只能一個一個的往下乘。
這也是為何要專門用一個!來表示階乘。
如果只想計算大概的值,可以用「
斯特林公式」
(請自行網路)。
其實想想也很自然,
100!=1x2x3x...x10x11x12x...x20x21x...x99x100,
從10以後,每乘一次,這個數就至少增加一位,所以這個數就是寫出來,也至少是100位左右的數字,假設有的話,這個公式該多復雜。
⑶ 階乘的計算方法
n!=1×2×3×...×n。階乘亦可以遞歸方式定義:0!=1,n!=(n-1)!×n。
亦即n!=1×2×3×...×n。階乘亦可以遞歸方式定義:0!=1,n!=(n-1)!×n。
⑷ 排列組合的演算法和階乘的公式
從5個不同的小球里任取三個,共有多少種取法?
屬於組合問題,C(3,5)=(5*4*3)/(3*2*1)=10種
從數字1、2、3、4、5中任取三個數組成一個新的三位數,共可組成多少個不同的三位數?
屬於排列問題,方法一,P(3,5)=5*4*3=60個
方法二,C(3,5)*P(3,3)=10*6=60個
「!」表示階乘,5!=5*4*3*2*1=120,3!=3*2*1=6
⑸ 階乘公式是什麼呢
階乘的主要公式:
1、任何大於1的自然數n階乘表示方法。
n!=1×2×3×……×n或n!=n×(n-1)!
2、n的雙階乘:當n為奇數時表示不大於n的所有奇數的乘積。
如:7!=1×3×5×7
3、當n為偶數時表示不大於n的所有偶數的乘積(除0外)。
如:8!=2×4×6×8
4、小於0的整數-n的階乘表示。
(-n)!=1 / (n+1)!
5、0的階乘。
0!=0
階乘計算方法:
正整數階乘指從1乘以2乘以3乘以4一直乘到所要求的數。例如所要求的數是4,則階乘式是1×2×3×4,得到的積是24,24就是4的階乘。
例如所要求的數是6,則階乘式是1×2×3×……×6,得到的積是720,720就是6的階乘。例如所要求的數是n,則階乘式是1×2×3×……×n,設得到的積是x,x就是n的階乘。
⑹ 階乘的主要公式
階乘的主要公式:
(6)排列階乘的計算方法擴展閱讀:
階乘(factorial)是基斯頓·卡曼(Christian Kramp, 1760 – 1826)於1808年發明的運算符號。階乘,也是數學里的一種術語。階乘指從1乘以2乘以3乘以4一直乘到所要求的數。
另外,數學家定義,0!=1,所以0!=1!通常我們所說的階乘是定義在自然數范圍里的,小數沒有階乘,像0.5!,0.65!,0.777!都是錯誤的。
但是,有時候我們會將Gamma函數定義為非整數的階乘,因為當x是正整數n的時候,Gamma函數的值是n-1的階乘。
⑺ 數學排列組合的階乘形式的推導過程
排列公式是建立一個模型,從n個不相同元素中取出m個排成一列(有序),第一個位置可以有n個選擇,第二個位置可以有n-1個選擇(已經有1個放在前一個位置),則同理可知第三個位置可以有n-2個選擇,以此類推第m個位置可以有n-m+1個選擇,則排列數A(n
m)=n*(n-1)*(n-2)...*(n-m+1)
由階乘的定義可知A(n
m)=[n*(n-1)*(n-2)...*(n-m+1)]*[(n-m)*(n-m-1)...*1]/[(n-m)*(n-m-1)...*1]
上下合並可得A(n
m)=n!/(n-m)!
組合公式對應另一個模型,取出m個成為一組(無序),可以先考慮排列A(n
m),由於m個元素組成的一組可以有m!種不同的排列(全排列A(m
m)=m!),所以組合的總數就是A(n
m)/m!
即為C(n
m)=A(n
m)/m!=n!/[m!*(n-m)!]
⑻ 排列組合公式計算公式是什麼
排列組合公式計算公式大全如下所示。
1、排列及計算公式
從n個不同元素中,任取m(m≤n)個元素按照一定的順序排成一列,叫做從n個不同元素中取出m個元素的一個排列;從n個不同元素中取出m(m≤n)個元素的所有排列的個數,叫做從n個不同元素中取出m個元素的排列數,用符號p(n,m)表示。p(n,m)=n(n-1)(n-2)…(n-m+1)= n!/(n-m)!(規定0!=1)。
2、組合及計算公式
從n個不同元素中,任取m(m≤n)個元素並成一組,叫做從n個不同元素中取出m個元素的一個組合;從n個不同元素中取出m(m≤n)個元素的所有組合的個數,叫做從n個不同元素中取出m個元素的組合數。
用符號c(n,m)表示,c(n,m)=p(n,m)/m!=n!/((n-m)!*m!),c(n,m)=c(n,n-m)。
3.其他排列與組合公式
從n個元素中取出r個元素的循環排列數=p(n,r)/r=n!/r(n-r)!。n個元素被分成k類,每類的個數分別是n1,n2,...nk這n個元素的全排列數為n!/(n1!*n2!*...*nk!)。k類元素,每類的個數無限,從中取出m個元素的組合數為c(m+k-1,m)。排列(Pnm(n為下標,m為上標))
Pnm=n×(n-1)-(n-m+1);Pnm=n!/(n-m)!(註:!是階乘符號);Pnn(兩個n分別為上標和下標)=n!;0!=1。
Pn1(n為下標1為上標)=n組合(Cnm(n為下標,m為上標))Cnm=Pnm/Pmm;Cnm=n!/m!(n-m)!;Cnn(兩個n分別為上標和下標)=1;Cn1(n為下標1為上標)=n;Cnm=Cnn-m。
⑼ 階乘的公式是什麼
公式:n!=n*(n-1)!
階乘的計算方法
階乘指從1乘以2乘以3乘以4一直乘到所要求的數。
例如所要求的數是4,則階乘式是1×2×3×4,得到的積是24,24就是4的階乘。
例如所要求的數是6,則階乘式是1×2×3×..×6,得到的積是720,720就是6的階乘。例如所要求的數是n,則階乘式是1×2×3×…×n,設得到的積是x,x就是n的階乘。
階乘的表示方法
在表達階乘時,就使用「!」來表示。如x的階乘,就表示為x!
他的原理就是反推,如,舉例,求10的階乘=10*9的階乘(以後用!表示階乘)那麼9!=?,9!=9*8!,8!=8*7!,7!=7*6!,6!=6*5!,5!=5*4!,4!=4*3!,
3!=3*2!,2!=2*1!,1的階乘是多少呢?是1
1!=1*1,數學家規定,0!=1,所以0!=1!然後在往前推算,公式為n!(n!為當前數所求的階乘)=n(當前數)*(n-1)!(比他少一的一個數n-1的階乘把公式列出來像後推,只有1的!為1,所以要從1開始,要知道3!要知道2!就要知道1!但必須從1!開始推算所以要像後推,如果遍程序演算法可以此公式用一個函數解決,並且嵌套調用次函數,,)把數帶入公式為,
1!=1*1
2!=2*1(1!)
3!=3*2(2!)
4=4*6(3!),如果要是編程,怎麼解決公式問題呢
首先定義演算法
//演算法,1,定義函數,求階乘,定義函數fun,參數值n,(#include
long
fun(int
n
)
//long
為長整型,因20!就很大了超過了兆億
(數學家定義數學家定義,0!=1,所以0!=1!,0與1的階乘沒有實際意義)
2,函數體判斷,如果這個數大於1,則執行if(n>1)(往回退算,這個數是10求它!,要從2的階乘值開始,所以執行公式的次數定義為9,特別需要注意的是此處,當前第一次寫入代碼執行,已經算一次)
求這個數的n階乘(公式為,n!=n*(n-1)!,並且反回一個值,
return
(n*(fun(n-1));(這個公式為,首先這個公式求的是10的階乘,但是求10的階乘就需要,9的階乘,9的階乘我們不知道,所以就把10減1,也就是n-1做為一個新的階乘,從新調用fun函數,求它的階乘然後在把這個值返回到
fun(n-1),然後執行n*它返回的值,其實這個公式就是調用fun函數的結果,函數值為return
返回的值,(n-1)為參數依次類推,...一值嵌套調用fun函數,
到把n-1的值=1,
注意:此時已經運行9次fun()函數算第一次運行,,調用幾次fun函數呢?8次函數,所以,n-1執行了9次,n-1=1
,n=2已經調用就可以求2乘階值