This will work for the factorial (although a very small subset) of positive integers:
unsigned long factorial(unsigned long f)
{
if ( f == 0 )
return 1;
return(f * factorial(f - 1));
}
printf("%i", factorial(5));
Due to the nature of your problem (and level that you have admitted), this solution is based more in the concept of solving this rather than a function that will be used in the next "Permutation Engine".
This calculates factorials of non-negative integers[*] up to ULONG_MAX, which will have so many digits that it's unlikely your machine can store a whole lot more, even if it has time to calculate them. Uses the GNU multiple precision library, which you need to link against.
$ make factorial CFLAGS="-L/bin/ -lcyggmp-3 -pedantic" -B && ./factorial
cc -L/bin/ -lcyggmp-3 -pedantic factorial.c -o factorial
100
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
[*] If you mean something else by "number" then you'll have to be more specific. I'm not aware of any other numbers for which the factorial is defined, despite valiant efforts by Pascal to extend the domain by use of the Gamma function.
--(基于产品,列表)变形和应用
目录 (n,c) [] = n
cata (n,c) (x:xs) = c (x, cata (n,c) xs)
mult = 咖喱 (*)
产品 = cata (1, mult)
--(基于联产品,列表)变形和应用
ana f = 任一 (const []) (cons .pair (id, ana f)) 。 f
缺点 = 不咖喱 (:)
downfrom = ana 不可数
不可计数 0 = 左 ()
不可数 n = 右 (n, n-1)
-- 列表亲质性的两种变体
hylo fg = 目录 g 。安娜夫
hylo' f (n,c) = 任一 (const n) (c .pair (id, hylo' f (c,n))) 。 f
对 (f,g) (x,y) = (fx, gy)
-- 阶乘的几个版本,全部(扩展上)等效
事实=产品。从下
fac' = hylo uncount (1, mult)
fac'' = hylo' uncount (1, mult)
博士。 Haskell程序员(吃了太多香蕉眼睛都肿了 出去,现在他需要新镜头!)
--基于函子的显式类型递归
newtype Mu f = Mu (f (Mu f)) 推导 显示
在 x = Mu x
输出 (Mu x) = x
-- cata-和ana-morphisms,现在用于*任意*(常规)基函子
卡塔 phi = phi . fmap(卡塔菲)。出去
ana psi = 在 . fmap (ana psi) 。磅/平方英寸
-- 自然数的基本函子和数据类型,
-- 使用柯里化消除运算符
数据 N b = 0 | Succ b 推导显示
实例函子 N 其中
fmap f = nelim 零 (Succ . f)
nelim zs 零 = z
nelim zs (Succ n) = sn
类型 Nat = Mu N
-- 转换为内部号码、便利性和应用程序
int = cata (nelim 0 (1+))
实例显示 Nat 在哪里
显示 = 显示 .整数
零=零
吸=吸进去。 Succ——请原谅我的“法语”(前奏冲突)
加 n = cata (nelim n 吸 )
mult n = cata(nelim 零(加 n))
-- 列表的基本函子和数据类型
数据 L ab = Nil |缺点 ab 派生 显示
实例函子 (L a) 其中
fmap f = lelim Nil (\ab -> Cons a (fb))
lelim nc 无 = n
lelim nc (Cons ab) = cab
类型列表 a = Mu (L a)
-- 转换为内部列表、便利性和应用程序
列表 = cata(lelim[](:))
实例显示=>显示(列表 a)其中
显示 = 显示 .列表
prod = cata(lelim(吸零)mult)
upto = ana(nelim Nil(diag(Cons.suck)).out)
诊断 fx = fxx
事实=产品。高达
博士后 Haskell 程序员
(摘自 Uustalu、Vene 和 Pardo 的“Comonads 的递归方案”[4])
-- 带有函子和变形的显式类型递归
新类型 Mu f = In (f (Mu f))
unIn (In x) = x
卡塔 phi = phi . fmap(卡塔菲)。未输入
-- 自然数的基本函子和数据类型,
-- 使用本地定义的“消除器”
数据 Nc = Z | SC
实例函子 N 其中
fmap g Z = Z
fmap g (S x) = S (gx)
类型 Nat = Mu N
零 = 在 Z 中
吸 n = In (S n)
添加 m = cata phi 其中
Φ Z = m
phi (S f) = 吸 f
mult m = cata phi 其中
phi Z = 零
phi (S f) = 添加 mf
-- 显式乘积及其功能作用
数据产品 ec = 对 ce
outl(xy 对)= x
outr(xy 对)= y
叉 fgx = 对 (fx) (gx)
实例函子 (Prod e) 其中
fmap g = fork (g . outl) outr
-- comonads,单子的绝对“对立面”
类函子 n => Comonad n 哪里
外部:: na ->一个
dupl::na-> n (na)
实例 Comonad (Prod e) 其中
外部 = 输出
dupl = 分叉 ID 外部
-- 广义变态、对称和拟态
gcata :: (函子 f, Comonad n) =>
(对于所有 a.f (na) -> n (fa))
-> (f(nc)→c)→ Mu f-> c
gcata 距离 phi = extr 。 cata(fmap phi .dist .fmap dupl)
zygo chi = gcata (fork (fmap outl) (chi . fmap outr))
para :: 函子 f => (f(Prod(Mu f)c)→c)→ Mu f-> c
para = zygo In
-- 阶乘,*困难*的方式!
fac = para phi 其中
phi Z = 吸零
phi (S (Pair fn)) = mult f (吸 n)
-- 为了方便和测试
int = cata phi 其中
ΦZ = 0
phi (S f) = 1 + f
实例显示 (Mu N) 其中
显示 = 显示 .整数
fac n = result (for init next done)
where init = (0,1)
next (i,m) = (i+1, m * (i+1))
done (i,_) = i==n
result (_,m) = m
for i n d = until d n i
Iterative one-liner Haskell programmer (former APL and C programmer)
fac n = snd (until ((>n) . fst) (\(i,m) -> (i+1, i*m)) (1,1))
Accumulating Haskell programmer (building up to a quick climax)
facAcc a 0 = a
facAcc a n = facAcc (n*a) (n-1)
fac = facAcc 1
Continuation-passing Haskell programmer (raised RABBITS in early years, then moved to New Jersey)
facCps k 0 = k 1
facCps k n = facCps (k . (n *)) (n-1)
fac = facCps id
Boy Scout Haskell programmer (likes tying knots; always “reverent,” he belongs to the Church of the Least Fixed-Point [8])
y f = f (y f)
fac = y (\f n -> if (n==0) then 1 else n * f (n-1))
Combinatory Haskell programmer (eschews variables, if not obfuscation; all this currying’s just a phase, though it seldom hinders)
s f g x = f x (g x)
k x y = x
b f g x = f (g x)
c f g x = f x g
y f = f (y f)
cond p f g x = if p x then f x else g x
fac = y (b (cond ((==) 0) (k 1)) (b (s (*)) (c b pred)))
List-encoding Haskell programmer (prefers to count in unary)
arb = () -- "undefined" is also a good RHS, as is "arb" :)
listenc n = replicate n arb
listprj f = length . f . listenc
listprod xs ys = [ i (x,y) | x<-xs, y<-ys ]
where i _ = arb
facl [] = listenc 1
facl n@(_:pred) = listprod n (facl pred)
fac = listprj facl
Interpretive Haskell programmer (never “met a language” he didn't like)
-- a dynamically-typed term language
data Term = Occ Var
| Use Prim
| Lit Integer
| App Term Term
| Abs Var Term
| Rec Var Term
type Var = String
type Prim = String
-- a domain of values, including functions
data Value = Num Integer
| Bool Bool
| Fun (Value -> Value)
instance Show Value where
show (Num n) = show n
show (Bool b) = show b
show (Fun _) = ""
prjFun (Fun f) = f
prjFun _ = error "bad function value"
prjNum (Num n) = n
prjNum _ = error "bad numeric value"
prjBool (Bool b) = b
prjBool _ = error "bad boolean value"
binOp inj f = Fun (\i -> (Fun (\j -> inj (f (prjNum i) (prjNum j)))))
-- environments mapping variables to values
type Env = [(Var, Value)]
getval x env = case lookup x env of
Just v -> v
Nothing -> error ("no value for " ++ x)
-- an environment-based evaluation function
eval env (Occ x) = getval x env
eval env (Use c) = getval c prims
eval env (Lit k) = Num k
eval env (App m n) = prjFun (eval env m) (eval env n)
eval env (Abs x m) = Fun (\v -> eval ((x,v) : env) m)
eval env (Rec x m) = f where f = eval ((x,f) : env) m
-- a (fixed) "environment" of language primitives
times = binOp Num (*)
minus = binOp Num (-)
equal = binOp Bool (==)
cond = Fun (\b -> Fun (\x -> Fun (\y -> if (prjBool b) then x else y)))
prims = [ ("*", times), ("-", minus), ("==", equal), ("if", cond) ]
-- a term representing factorial and a "wrapper" for evaluation
facTerm = Rec "f" (Abs "n"
(App (App (App (Use "if")
(App (App (Use "==") (Occ "n")) (Lit 0))) (Lit 1))
(App (App (Use "*") (Occ "n"))
(App (Occ "f")
(App (App (Use "-") (Occ "n")) (Lit 1))))))
fac n = prjNum (eval [] (App facTerm (Lit n)))
Static Haskell programmer (he does it with class, he’s got that fundep Jones! After Thomas Hallgren’s “Fun with Functional Dependencies” [7])
-- static Peano constructors and numerals
data Zero
data Succ n
type One = Succ Zero
type Two = Succ One
type Three = Succ Two
type Four = Succ Three
-- dynamic representatives for static Peanos
zero = undefined :: Zero
one = undefined :: One
two = undefined :: Two
three = undefined :: Three
four = undefined :: Four
-- addition, a la Prolog
class Add a b c | a b -> c where
add :: a -> b -> c
instance Add Zero b b
instance Add a b c => Add (Succ a) b (Succ c)
-- multiplication, a la Prolog
class Mul a b c | a b -> c where
mul :: a -> b -> c
instance Mul Zero b Zero
instance (Mul a b c, Add b c d) => Mul (Succ a) b d
-- factorial, a la Prolog
class Fac a b | a -> b where
fac :: a -> b
instance Fac Zero One
instance (Fac n k, Mul (Succ n) k m) => Fac (Succ n) m
-- try, for "instance" (sorry):
--
-- :t fac four
Beginning graduate Haskell programmer (graduate education tends to liberate one from petty concerns about, e.g., the efficiency of hardware-based integers)
-- the natural numbers, a la Peano
data Nat = Zero | Succ Nat
-- iteration and some applications
iter z s Zero = z
iter z s (Succ n) = s (iter z s n)
plus n = iter n Succ
mult n = iter Zero (plus n)
-- primitive recursion
primrec z s Zero = z
primrec z s (Succ n) = s n (primrec z s n)
-- two versions of factorial
fac = snd . iter (one, one) (\(a,b) -> (Succ a, mult a b))
fac' = primrec one (mult . Succ)
-- for convenience and testing (try e.g. "fac five")
int = iter 0 (1+)
instance Show Nat where
show = show . int
(zero : one : two : three : four : five : _) = iterate Succ Zero
Origamist Haskell programmer
(always starts out with the “basic Bird fold”)
-- (curried, list) fold and an application
fold c n [] = n
fold c n (x:xs) = c x (fold c n xs)
prod = fold (*) 1
-- (curried, boolean-based, list) unfold and an application
unfold p f g x =
if p x
then []
else f x : unfold p f g (g x)
downfrom = unfold (==0) id pred
-- hylomorphisms, as-is or "unfolded" (ouch! sorry ...)
refold c n p f g = fold c n . unfold p f g
refold' c n p f g x =
if p x
then n
else c (f x) (refold' c n p f g (g x))
-- several versions of factorial, all (extensionally) equivalent
fac = prod . downfrom
fac' = refold (*) 1 (==0) id pred
fac'' = refold' (*) 1 (==0) id pred
Cartesianally-inclined Haskell programmer (prefers Greek food, avoids the spicy Indian stuff; inspired by Lex Augusteijn’s “Sorting Morphisms” [3])
-- (product-based, list) catamorphisms and an application
cata (n,c) [] = n
cata (n,c) (x:xs) = c (x, cata (n,c) xs)
mult = uncurry (*)
prod = cata (1, mult)
-- (co-product-based, list) anamorphisms and an application
ana f = either (const []) (cons . pair (id, ana f)) . f
cons = uncurry (:)
downfrom = ana uncount
uncount 0 = Left ()
uncount n = Right (n, n-1)
-- two variations on list hylomorphisms
hylo f g = cata g . ana f
hylo' f (n,c) = either (const n) (c . pair (id, hylo' f (c,n))) . f
pair (f,g) (x,y) = (f x, g y)
-- several versions of factorial, all (extensionally) equivalent
fac = prod . downfrom
fac' = hylo uncount (1, mult)
fac'' = hylo' uncount (1, mult)
Ph.D. Haskell programmer (ate so many bananas that his eyes bugged out, now he needs new lenses!)
-- explicit type recursion based on functors
newtype Mu f = Mu (f (Mu f)) deriving Show
in x = Mu x
out (Mu x) = x
-- cata- and ana-morphisms, now for *arbitrary* (regular) base functors
cata phi = phi . fmap (cata phi) . out
ana psi = in . fmap (ana psi) . psi
-- base functor and data type for natural numbers,
-- using a curried elimination operator
data N b = Zero | Succ b deriving Show
instance Functor N where
fmap f = nelim Zero (Succ . f)
nelim z s Zero = z
nelim z s (Succ n) = s n
type Nat = Mu N
-- conversion to internal numbers, conveniences and applications
int = cata (nelim 0 (1+))
instance Show Nat where
show = show . int
zero = in Zero
suck = in . Succ -- pardon my "French" (Prelude conflict)
plus n = cata (nelim n suck )
mult n = cata (nelim zero (plus n))
-- base functor and data type for lists
data L a b = Nil | Cons a b deriving Show
instance Functor (L a) where
fmap f = lelim Nil (\a b -> Cons a (f b))
lelim n c Nil = n
lelim n c (Cons a b) = c a b
type List a = Mu (L a)
-- conversion to internal lists, conveniences and applications
list = cata (lelim [] (:))
instance Show a => Show (List a) where
show = show . list
prod = cata (lelim (suck zero) mult)
upto = ana (nelim Nil (diag (Cons . suck)) . out)
diag f x = f x x
fac = prod . upto
Post-doc Haskell programmer
(from Uustalu, Vene and Pardo’s “Recursion Schemes from Comonads” [4])
-- explicit type recursion with functors and catamorphisms
newtype Mu f = In (f (Mu f))
unIn (In x) = x
cata phi = phi . fmap (cata phi) . unIn
-- base functor and data type for natural numbers,
-- using locally-defined "eliminators"
data N c = Z | S c
instance Functor N where
fmap g Z = Z
fmap g (S x) = S (g x)
type Nat = Mu N
zero = In Z
suck n = In (S n)
add m = cata phi where
phi Z = m
phi (S f) = suck f
mult m = cata phi where
phi Z = zero
phi (S f) = add m f
-- explicit products and their functorial action
data Prod e c = Pair c e
outl (Pair x y) = x
outr (Pair x y) = y
fork f g x = Pair (f x) (g x)
instance Functor (Prod e) where
fmap g = fork (g . outl) outr
-- comonads, the categorical "opposite" of monads
class Functor n => Comonad n where
extr :: n a -> a
dupl :: n a -> n (n a)
instance Comonad (Prod e) where
extr = outl
dupl = fork id outr
-- generalized catamorphisms, zygomorphisms and paramorphisms
gcata :: (Functor f, Comonad n) =>
(forall a. f (n a) -> n (f a))
-> (f (n c) -> c) -> Mu f -> c
gcata dist phi = extr . cata (fmap phi . dist . fmap dupl)
zygo chi = gcata (fork (fmap outl) (chi . fmap outr))
para :: Functor f => (f (Prod (Mu f) c) -> c) -> Mu f -> c
para = zygo In
-- factorial, the *hard* way!
fac = para phi where
phi Z = suck zero
phi (S (Pair f n)) = mult f (suck n)
-- for convenience and testing
int = cata phi where
phi Z = 0
phi (S f) = 1 + f
instance Show (Mu N) where
show = show . int
Tenured professor (teaching Haskell to freshmen)
fac n = product [1..n]
Content from The Evolution of a Haskell Programmer by Fritz Ruehr, Willamette University - 11 July 01
int factorial(int n)
{
int result = 1;
for (int i = 2; i <= n; i++)
{
result *= i;
}
return result;
}
C 不是函数式语言,您不能依赖尾部调用优化。因此,除非需要,否则不要在 C(或 Java)中使用递归。
仅仅因为阶乘经常被用作递归的第一个示例,并不意味着您需要递归来计算它。
仅仅
如果 n 太大,这将静静地溢出,这是 C(和 Java)中的惯例。
如果
如果 int 可以表示的数字对于您要计算的阶乘来说太小,则选择其他数字类型。如果需要更大一点,则为 long long;如果 n 不太大并且您不介意一些不精确,则为 float 或 double;如果您想要真正大阶乘的精确值,则为大整数。
In C99 (or Java) I would write the factorial function iteratively like this:
int factorial(int n)
{
int result = 1;
for (int i = 2; i <= n; i++)
{
result *= i;
}
return result;
}
C is not a functional language and you can't rely on tail-call optimization. So don't use recursion in C (or Java) unless you need to.
Just because factorial is often used as the first example for recursion it doesn't mean you need recursion to compute it.
This will overflow silently if n is too big, as is the custom in C (and Java).
If the numbers int can represent are too small for the factorials you want to compute then choose another number type. long long if it needs be just a little bit bigger, float or double if n isn't too big and you don't mind some imprecision, or big integers if you want the exact values of really big factorials.
Here's a C program that uses OPENSSL's BIGNUM implementation, and therefore is not particularly useful for students. (Of course accepting a BIGNUM as the input parameter is crazy, but helpful for demonstrating interaction between BIGNUMs).
#include <stdio.h>
#include <stdlib.h>
int main()
{
int x, number, fac;
fac = 1;
printf("Enter a number:\n");
scanf("%d",&number);
if(number<0)
{
printf("Factorial not defined for negative numbers.\n");
exit(0);
}
for(x = 1; x <= number; x++)
{
if (number >= 0)
fac = fac * x;
else
fac=1;
}
printf("%d! = %d\n", number, fac);
}
You use the following code to do it.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int x, number, fac;
fac = 1;
printf("Enter a number:\n");
scanf("%d",&number);
if(number<0)
{
printf("Factorial not defined for negative numbers.\n");
exit(0);
}
for(x = 1; x <= number; x++)
{
if (number >= 0)
fac = fac * x;
else
fac=1;
}
printf("%d! = %d\n", number, fac);
}
double logfactorial(int n) {
double fac = 0.0;
for ( ; n>1 ; n--) fac += log(fac);
return fac;
}
For large numbers you probably can get away with an approximate solution, which tgamma gives you (n! = Gamma(n+1)) from math.h. If you want even larger numbers, they won't fit in a double, so you should use lgamma (natural log of the gamma function) instead.
If you're working somewhere without a full C99 math.h, you can easily do this type of thing yourself:
double logfactorial(int n) {
double fac = 0.0;
for ( ; n>1 ; n--) fac += log(fac);
return fac;
}
I don't think I'd use this in most cases, but one well-known practice which is becoming less widely used is to have a look-up table. If we're only working with built-in types, the memory hit is tiny.
Just another approach, to make the poster aware of a different technique. Many recursive solutions also can be memoized whereby a lookup table is filled in when the algorithm runs, drastically reducing the cost on future calls (kind of like the principle behind .NET JIT compilation I guess).
main()
{
int n;
scanf("%d",&n);
printf("%ld",fact(n));
}
long int fact(int n)
{
long int facto=1;
int i;
for(i=1;i<=n;i++)
{
facto=facto*i;
}
return facto;
}
We have to start from 1 to the limit specfied say n.Start from 1*2*3...*n.
In c, i am writing it as a function.
main()
{
int n;
scanf("%d",&n);
printf("%ld",fact(n));
}
long int fact(int n)
{
long int facto=1;
int i;
for(i=1;i<=n;i++)
{
facto=facto*i;
}
return facto;
}
Simplest and most efficient is to sum up logarithms. If you use Log10 you get power and exponent.
Pseudocode
r=0
for i from 1 to n
r= r + log(i)/log(10)
print "result is:", 10^(r-floor(r)) ,"*10^" , floor(r)
You might need to add the code so the integer part does not increase too much and thus decrease accuracy, but result should be ok for even very large factorials.
#include<stdio.h>
int main(){
int i=1,f=1,n;
printf("\n\nEnter a number: ");
scanf("%d",&n);
while(i<=n){
f=f*i;
i++;
}
printf("Factorial of is: %d",f);
getch();
}
I used this code for Factorial:
#include<stdio.h>
int main(){
int i=1,f=1,n;
printf("\n\nEnter a number: ");
scanf("%d",&n);
while(i<=n){
f=f*i;
i++;
}
printf("Factorial of is: %d",f);
getch();
}
I would do this with a pre-calculated lookup table as suggested by Mr. Boy. This would be faster to calculate than an iterative or recursive solution. It relies on how fast n! grows, because the largest n! you can calculate without overflowing an unsigned long long (max value of 18,446,744,073,709,551,615) is only 20!, so you only need an array with 21 elements. Here's how it would look in c:
long long factorial (int n) {
long long f[22] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600, 6227020800, 87178291200, 1307674368000, 20922789888000, 355687428096000, 6402373705728000, 121645100408832000, 2432902008176640000, 51090942171709440000};
return f[n];
}
发布评论
评论(19)
这适用于正整数的阶乘(尽管是一个非常小的子集):
由于您的问题的性质(以及您已经承认的水平),该解决方案更多地基于解决这个问题的概念,而不是基于一个函数将在下一个“排列引擎”中使用。
This will work for the factorial (although a very small subset) of positive integers:
Due to the nature of your problem (and level that you have admitted), this solution is based more in the concept of solving this rather than a function that will be used in the next "Permutation Engine".
这会计算直到 ULONG_MAX 的非负整数[*] 的阶乘,其中的位数太多,以至于您的机器不太可能存储更多的位数,即使它有时间计算它们。使用 GNU 多精度库,您需要链接该库。
示例输出:
[*] 如果您用“数字”表示其他内容,那么您必须更具体。尽管 Pascal 做出了勇敢的努力,通过使用 Gamma 函数来扩展域,但我不知道定义了阶乘的任何其他数字。
This calculates factorials of non-negative integers[*] up to ULONG_MAX, which will have so many digits that it's unlikely your machine can store a whole lot more, even if it has time to calculate them. Uses the GNU multiple precision library, which you need to link against.
Example output:
[*] If you mean something else by "number" then you'll have to be more specific. I'm not aware of any other numbers for which the factorial is defined, despite valiant efforts by Pascal to extend the domain by use of the Gamma function.
当你可以在 Haskell 中实现时,为什么要在 C 中实现呢:
Why do it in C when you can do it in Haskell:
感谢 Christoph,一个适用于相当多“数字”的 C99 解决方案:
产生 6.000000 120.000000
Thanks to Christoph, a C99 solution that works for quite a few "numbers":
produces 6.000000 120.000000
对于大 n,您可能会遇到一些问题,您可能需要使用斯特林近似:
即:
For large n you may run into some issues and you may want to use Stirling's approximation:
Which is:
如果您的主要目标是一个看起来有趣的函数:(
不推荐作为实际使用的算法。)
If your main objective is an interesting looking function:
(Not recommended as an algorithm for real use.)
尾递归版本:
a tail-recursive version:
在 C99(或 Java)中,我会像这样迭代地编写阶乘函数:
C 不是函数式语言,您不能依赖尾部调用优化。因此,除非需要,否则不要在 C(或 Java)中使用递归。
仅仅因为阶乘经常被用作递归的第一个示例,并不意味着您需要递归来计算它。
仅仅
如果 n 太大,这将静静地溢出,这是 C(和 Java)中的惯例。
如果
如果 int 可以表示的数字对于您要计算的阶乘来说太小,则选择其他数字类型。如果需要更大一点,则为 long long;如果 n 不太大并且您不介意一些不精确,则为 float 或 double;如果您想要真正大阶乘的精确值,则为大整数。
In C99 (or Java) I would write the factorial function iteratively like this:
C is not a functional language and you can't rely on tail-call optimization. So don't use recursion in C (or Java) unless you need to.
Just because factorial is often used as the first example for recursion it doesn't mean you need recursion to compute it.
This will overflow silently if n is too big, as is the custom in C (and Java).
If the numbers int can represent are too small for the factorials you want to compute then choose another number type. long long if it needs be just a little bit bigger, float or double if n isn't too big and you don't mind some imprecision, or big integers if you want the exact values of really big factorials.
这是一个使用 OPENSSL 的 BIGNUM 实现的 C 程序,因此对学生来说不是特别有用。 (当然,接受 BIGNUM 作为输入参数是疯狂的,但有助于演示 BIGNUM 之间的交互)。
此测试程序展示了如何创建输入数字以及如何处理返回值:
使用 gcc 编译:
Here's a C program that uses OPENSSL's BIGNUM implementation, and therefore is not particularly useful for students. (Of course accepting a BIGNUM as the input parameter is crazy, but helpful for demonstrating interaction between BIGNUMs).
This test program shows how to create a number for input and what to do with the return value:
Compiled with gcc:
您可以使用以下代码来完成此操作。
You use the following code to do it.
对于大数,您可能可以得到一个近似解,tgamma 可以从 math.h 中为您提供 (n!= Gamma(n+1))。如果您想要更大的数字,它们将无法容纳在双精度数中,因此您应该使用 lgamma(gamma 函数的自然对数)。
如果您在没有完整 C99 math.h 的地方工作,您可以自己轻松地执行此类操作:
For large numbers you probably can get away with an approximate solution, which
tgamma
gives you (n! = Gamma(n+1)) from math.h. If you want even larger numbers, they won't fit in a double, so you should uselgamma
(natural log of the gamma function) instead.If you're working somewhere without a full C99 math.h, you can easily do this type of thing yourself:
我认为在大多数情况下我不会使用它,但一种正在变得越来越不广泛使用的众所周知的做法是使用查找表。如果我们只使用内置类型,那么内存占用很小。
这只是另一种方法,让发布者意识到不同的技术。许多递归解决方案也可以被记忆,从而在算法运行时填充查找表,从而大大降低未来调用的成本(我猜有点像 .NET JIT 编译背后的原理)。
I don't think I'd use this in most cases, but one well-known practice which is becoming less widely used is to have a look-up table. If we're only working with built-in types, the memory hit is tiny.
Just another approach, to make the poster aware of a different technique. Many recursive solutions also can be memoized whereby a lookup table is filled in when the algorithm runs, drastically reducing the cost on future calls (kind of like the principle behind .NET JIT compilation I guess).
我们必须从
1
开始到指定的限制,例如n
。从1*2*3...*n
开始。在c中,我把它写成一个函数。
We have to start from
1
to the limit specfied sayn
.Start from1*2*3...*n
.In c, i am writing it as a function.
简单的解决方案:
Simple solution:
最简单、最有效的是对数求和。如果您使用
Log10
,您将获得幂和指数。伪代码
您可能需要添加代码,以便整数部分不会增加太多,从而降低准确性,但即使对于非常大的阶乘,结果也应该没问题。
Simplest and most efficient is to sum up logarithms. If you use
Log10
you get power and exponent.Pseudocode
You might need to add the code so the integer part does not increase too much and thus decrease accuracy, but result should be ok for even very large factorials.
C 中使用递归的示例
Example in C using recursion
我使用以下代码进行阶乘:
I used this code for Factorial:
我会按照 先生的建议使用预先计算的查找表来完成此操作。男孩。这比迭代或递归解决方案计算得更快。它依赖于
n!
增长的速度,因为您可以在不溢出unsigned long long
的情况下计算出最大的n!
(最大值为 18,446,744,073,709,551,615)只有20!
,因此您只需要一个包含 21 个元素的数组。下面是它在 c 中的样子:亲自看看!
I would do this with a pre-calculated lookup table as suggested by Mr. Boy. This would be faster to calculate than an iterative or recursive solution. It relies on how fast
n!
grows, because the largestn!
you can calculate without overflowing anunsigned long long
(max value of 18,446,744,073,709,551,615) is only20!
, so you only need an array with 21 elements. Here's how it would look in c:See for yourself!