基本介紹
- 中文名:階乘
- 外文名:factorial
- 分類:數學
- 提出者:基斯頓卡曼
- 時間:1808年
- 特點:小於及等於該數的正整數的積
概念
計算方法
定義範圍
雙階乘
這樣把階乘拓展到負數區間,形成了負數區間的周期震盪階乘函式。
拓展與再定義
廣義複數階乘
套用
可以將n!表示成10的次冪,即n!=10^M(10的M次方)則不小於M的最小整數就是 n!的位數,對該式兩邊取對數,有 M =log10^n!
即:
M = log10^1+log10^2+log10^3...+log10^n
循環求和,就能算得M值,該M是n!的精確位數
#include "iostream"#include "math.h"using namespace std;int main(){ int n,i; double d; while (scanf("%d",&n)!=EOF){ d=0; for (i=1;i<=n;i++)d+=(double)log10(i); printf("%d\n",(int)d+1); }return 0;}
利用斯特林(Stirling)公式的進行求解。下面是推導得到的公式:
res=(long)( (log10(sqrt(4.0*acos(0.0)*n)) + n*(log10(n)-log10(exp(1.0)))) + 1 );
當n=1的時候,上面的公式不適用,所以要單獨處理n=1的情況!
有關斯特林(Stirling)公式及其相關推導,這裡就不進行詳細描述,
#include <cstdio>#include <iostream>using namespace std;int main(){ int N,i,mod5,d5,count0=0; scanf("%d",&N); for (i=1;i<=N;i++) { mod5=i%5; d5=i/5; while(mod5==0) { count0++; mod5=d5%5; d5=d5/5; } } printf("%d的個數 %d\n",N,count0);}
計算機階乘
(defun factorial (n) (cond ((> n 0) (* (factorial (- n 1)) n)) ((= n 0) 1) (t (error "N is smaller than 0."))))
def factorial(n) if(n<=1): return 1 else: return factorial(n-1) * n
#include<stdio.h>int main(){ int n, x; for(n = x = 1; n <= 10; ++n) { x *= n; printf("%d\t%d\n", n, x); } return 0;}
program test;varn:longint;function jc(n:longint):qword;begin if n=0 then jc:=1 else jc:=n*jc(n-1)end;begin readln (n); writeln (jc(n))end.
#include<iostream>using namespace std;long long f(int n){ long long e=1; if(n>0) e=n*f(n-1); cout<<n<<"!="<<e<<endl; return e;}int main(){ int m=20; f(m); return 0;}
#include<cstdio>#include<cmath>double s;const double e=exp(1.0);double F(double t){ return pow(t,s)*pow(e,-t);}double simpson(double a,double b){ double c=a+(b-a)/2; return (F(a)+4*F(c)+F(b))*(b-a)/6;}double asr(double a,double b,double eps,double A){ double c=a+(b-a)/2; double L=simpson(a,c),R=simpson(c,b); if(fabs(L+R-A)<=15*eps) return L+R+(L+R-A)/15.0; return asr(a,c,eps/2,L)+asr(c,b,eps/2,R);}double asr(double a,double b,double eps){ return asr(a,b,eps,simpson(a,b));}int main(){ scanf("%lf",&s); printf("%lf\n",asr(0,1e2,1e-10)); return 0;}
public class Main{ final static int MAX=20;// 可以替換 MAX 的值。 public static void main(String[] args) { int i=1; long result=1; long[] n=new long[MAX]; do{ result*=(i+1); System.out.println(i+1+"!="+result); n[i]=result; i++; }while(i<MAX); n[0]=1;//階乘end }}
public static void main(String[] args) { long result = 1; for (int j = 0; j < 10; j++) { result *= (j + 1); System.out.println(j + 1 + "!=" + result); }}
function jc($n){if($n>1){return $n*jc($n-1);}else{return 1;}}echo jc(3);
function factorial(num){ if (num <= 1) return 1; else return num * arguments.callee(num - 1);};
.286.model small,stdcallFactorial PROTO :WORD.stack 200h.data f_n WORD 6 result WORD ?.CODESTART: mov ax,@data mov ds,ax mov es,ax invoke Factorial,f_n mov result,ax mov ah,4ch int 21h ;計算階乘 ;輸入參數:[ebp+8] = n, 需要計算的數字 ;返回參數:eax = n的階乘 Factorial PROC near uses bx,fn mov ax,fn cmp ax,0 ja L1 mov ax,1 jmp L2 L1: dec ax invoke Factorial,ax ReturnFact: mov bx,fn mul bx L2: retFactorial ENDPEND START
高精度求階乘
Dim 階乘數 As Decimal = CDec(InputBox("請輸入一個數值,將得到它的階乘結果。"))
' 因為要計算比較大的數值,因此將較小的整數值按照階乘的定義來計算得到準確值,但 VBULong整數的最大範圍能計算到 20的階乘,21將溢出;較大的數值或者小數按照 Stirling 逼近的方式計算。
If 階乘數 >= 0 And 階乘數 <= 20 And Fix(階乘數) = 階乘數 Then
MsgBox(階乘數 & " 的階乘結果是:" & 小階乘(CInt(階乘數)))
Else
MsgBox(階乘數 & " 的階乘結果是:" & 大數階乘(CDbl(階乘數)) & " E " & 大數階乘指數(階乘數))
End If
End Sub
If 階乘數 = 0 Or 階乘數 = 1 Then'如果數值是 0或者 1,直接返回 1。
Return 1
Else
小階乘 = 1
For 階乘次數 As Integer = 1 To CInt(階乘數)
小階乘 *= CULng(階乘次數)
Next
Return 小階乘
End If
End Function
''' 這個過程用 Stirling 逼近的方式計算較大數值和有小數點的值的階乘結果的前 15 位。詳細過程見《用 Stirling 逼近近似計算階乘的探討與套用》一書。
''' </summary>
''' <param name="階乘數"></param>
''' <returns></returns>
''' <remarks></remarks>
Private Function 大數階乘(階乘數 As Double) As Double
Dim X As Double = 0.5 * Math.Log(2 * 階乘數 * Math.PI) / Math.Log(10) + 階乘數 * Math.Log(階乘數 / Math.Exp(1)) / Math.Log(10)
Dim XDouble As Double = X - Math.Truncate(X)
Dim Y As Double = Math.Exp(XDouble * Math.Log(10))
Dim Z As Double = Math.Exp(1 / 12 / 階乘數 - 1 / 360 / 階乘數 / 階乘數)
Return Y * Z
End Function
''' 這個過程用 Stirling 逼近的方式計算較大數值和有小數點的值的階乘結果的小數點位數。詳細過程見《用 Stirling 逼近近似計算階乘的探討與套用》一書。
''' </summary>
''' <param name="階乘數"></param>
''' <returns></returns>
''' <remarks></remarks>
Dim X As Double = 2 * Math.PI * 階乘數
Dim Y As Double = 0.5 * Math.Log10(X)
Dim A As Double = 階乘數 * Math.Log10(階乘數 / Math.E)
Return CULng(Math.Truncate(Y + A))
End Function
#include<stdio.h>#define N 5000//modify it to hold larger number//to avoid stack overflow, define it as global varibleint f[N];//do not need to be assigned as 0 because it has already been assigned 0 by the systemint main(){ int n,i,j,s,up; scanf("%d",&n); for(i=2,f[0]=1;i<=n;i++) { for(j=up=0;j<N;j++) { s=f[j]*i+up; f[j]=s%10; up=s/10; } } for(i=N-1;f[i]==0;i--); for(;i>=0;i--) printf("%d",f[i]); printf("\n"); return 0;}
var a:array[1..10000] of integer; b,c,d,t,x:integer;begin readln (x); if (x<0) then begin writeln ('error!'); readln; halt; end; for t:=1 to 10000 do a[t]:=0; d:=1; a[1]:=1; for c:=1 to x do {一直乘到x} begin t:=1; b:=0; {t:第幾位數 b:進位 d:總位數} repeat a[t]:=a[t]*c+b; {數組每位均乘上c,同時加上進位} b:=a[t] div 10; {分離出進位} if a[t]>=10 then if (t=d) then d:=d+1; {假如最後一位乘時有} {進位,則總位數加1} a[t]:=a[t] mod 10; inc (t); {數組下一位} until (t>d); {直到乘完數組的每一位數字} end; for t:=d downto 1 do write (a[t]); {輸出}end.