How do I find a factorial? [closed]

旧城冷巷雨未停 提交于 2019-11-27 04:12:38

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.

#include <assert.h> #include <stdio.h> #include <stdlib.h> #include <gmp.h>  void factorial(mpz_t result, unsigned long input) {     mpz_set_ui(result, 1);     while (input > 1) {         mpz_mul_ui(result, result, input--);     } }  int main() {     mpz_t fact;     unsigned long input = 0;     char *buf;      mpz_init(fact);     scanf("%lu", &input);     factorial(fact, input);      buf = malloc(mpz_sizeinbase(fact, 10) + 1);     assert(buf);     mpz_get_str(buf, 10, fact);     printf("%s\n", buf);      free(buf);     mpz_clear(fact); } 

Example output:

$ 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.

Why doing it in C when you can do it in Haskell:

Freshman Haskell programmer

fac n = if n == 0             then 1            else n * fac (n-1) 

Sophomore Haskell programmer, at MIT (studied Scheme as a freshman)

fac = (\(n) ->         (if ((==) n 0)             then 1             else ((*) n (fac ((-) n 1))))) 

Junior Haskell programmer (beginning Peano player)

fac  0    =  1 fac (n+1) = (n+1) * fac n 

Another junior Haskell programmer (read that n+k patterns are “a disgusting part of Haskell” 1 and joined the “Ban n+k patterns”-movement [2])

fac 0 = 1 fac n = n * fac (n-1) 

Senior Haskell programmer (voted for Nixon Buchanan Bush — “leans right”)

fac n = foldr (*) 1 [1..n] 

Another senior Haskell programmer (voted for McGovern Biafra Nader — “leans left”)

fac n = foldl (*) 1 [1..n] 

Yet another senior Haskell programmer (leaned so far right he came back left again!)

-- using foldr to simulate foldl  fac n = foldr (\x g n -> g (x*n)) id [1..n] 1 

Memoizing Haskell programmer (takes Ginkgo Biloba daily)

facs = scanl (*) 1 [1..]  fac n = facs !! n 

Pointless (ahem) “Points-free” Haskell programmer (studied at Oxford)

fac = foldr (*) 1 . enumFromTo 1 

Iterative Haskell programmer (former Pascal programmer)

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] 

Thanks to Christoph, a C99 solution that works for quite a few "numbers":

#include <math.h> #include <stdio.h>  double fact(double x) {   return tgamma(x+1.); }  int main() {   printf("%f %f\n", fact(3.0), fact(5.0));   return 0; } 

produces 6.000000 120.000000

ast4

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:

int facorial(int a) {    int b = 1, c, d, e;    a--;    for (c = a; c > 0; c--)    for (d = b; d > 0; d--)    for (e = c; e > 0; e--)    b++;    return b; } 

(Not recommended as an algorithm for real use.)

a tail-recursive version:

long factorial(long n) {     return tr_fact(n, 1); } static long tr_fact(long n, long result) {     if(n==1)         return result;     else         return tr_fact(n-1, n*result); } 

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> #include <assert.h> #include <openssl/crypto.h> #include <openssl/bn.h>  BIGNUM *factorial(const BIGNUM *num) {     BIGNUM *count = BN_new();     BIGNUM *fact = NULL;     BN_CTX *ctx = NULL;      BN_one(count);     if( BN_cmp(num, BN_value_one()) <= 0 )     {         return count;     }      ctx = BN_CTX_new();     fact = BN_dup(num);     BN_sub(count, fact, BN_value_one());     while( BN_cmp(count, BN_value_one()) > 0 )     {         BN_mul(fact, count, fact, ctx);         BN_sub(count, count, BN_value_one());     }      BN_CTX_free(ctx);     BN_free(count);      return fact; } 

This test program shows how to create a number for input and what to do with the return value:

int main(int argc, char *argv[]) {     const char *test_cases[] =     {         "0", "1",         "1", "1",         "4", "24",         "15", "1307674368000",         "30", "265252859812191058636308480000000",         "56", "710998587804863451854045647463724949736497978881168458687447040000000000000",         NULL, NULL     };     int index = 0;     BIGNUM *bn = NULL;     BIGNUM *fact = NULL;     char *result_str = NULL;      for( index = 0; test_cases[index] != NULL; index += 2 )     {         BN_dec2bn(&bn, test_cases[index]);          fact = factorial(bn);          result_str = BN_bn2dec(fact);         printf("%3s: %s\n", test_cases[index], result_str);         assert(strcmp(result_str, test_cases[index + 1]) == 0);          OPENSSL_free(result_str);         BN_free(fact);         BN_free(bn);         bn = NULL;     }      return 0; } 

Compiled with gcc:

gcc factorial.c -o factorial -g -lcrypto 
int factorial(int n){     return n <= 1 ? 1 : n * factorial(n-1); } 
#Newbie programmer def factorial(x):     if x == 0:         return 1     else:         return x * factorial(x - 1) print factorial(6)   #First year programmer, studied Pascal def factorial(x):     result = 1     i = 2     while i <= x:         result = result * i         i = i + 1     return result print factorial(6)   #First year programmer, studied C def fact(x): #{     result = i = 1;     while (i <= x): #{         result *= i;         i += 1;     #}     return result; #} print(fact(6))   #First year programmer, SICP @tailcall def fact(x, acc=1):     if (x > 1): return (fact((x - 1), (acc * x)))     else:       return acc print(fact(6))   #First year programmer, Python def Factorial(x):     res = 1     for i in xrange(2, x + 1):         res *= i     return res print Factorial(6)   #Lazy Python programmer def fact(x):     return x > 1 and x * fact(x - 1) or 1 print fact(6)   #Lazier Python programmer f = lambda x: x and x * f(x - 1) or 1 print f(6)   #Python expert programmer import operator as op import functional as f fact = lambda x: f.foldl(op.mul, 1, xrange(2, x + 1)) print fact(6)   #Python hacker import sys @tailcall def fact(x, acc=1):     if x: return fact(x.__sub__(1), acc.__mul__(x))     return acc sys.stdout.write(str(fact(6)) + '\n')   #EXPERT PROGRAMMER import c_math fact = c_math.fact print fact(6)   #ENGLISH EXPERT PROGRAMMER import c_maths fact = c_maths.fact print fact(6)   #Web designer def factorial(x):     #-------------------------------------------------     #--- Code snippet from The Math Vault          ---     #--- Calculate factorial (C) Arthur Smith 1999 ---     #-------------------------------------------------     result = str(1)     i = 1 #Thanks Adam     while i <= x:         #result = result * i  #It's faster to use *=         #result = str(result * result + i)            #result = int(result *= i) #??????         result str(int(result) * i)         #result = int(str(result) * i)         i = i + 1     return result print factorial(6)   #Unix programmer import os def fact(x):     os.system('factorial ' + str(x)) fact(6)   #Windows programmer NULL = None def CalculateAndPrintFactorialEx(dwNumber,                                  hOutputDevice,                                  lpLparam,                                  lpWparam,                                  lpsscSecurity,                                  *dwReserved):     if lpsscSecurity != NULL:         return NULL #Not implemented     dwResult = dwCounter = 1     while dwCounter <= dwNumber:         dwResult *= dwCounter         dwCounter += 1     hOutputDevice.write(str(dwResult))     hOutputDevice.write('\n')     return 1 import sys CalculateAndPrintFactorialEx(6, sys.stdout, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)   #Enterprise programmer def new(cls, *args, **kwargs):     return cls(*args, **kwargs)  class Number(object):     pass  class IntegralNumber(int, Number):     def toInt(self):         return new (int, self)  class InternalBase(object):     def __init__(self, base):         self.base = base.toInt()      def getBase(self):         return new (IntegralNumber, self.base)  class MathematicsSystem(object):     def __init__(self, ibase):         Abstract      @classmethod     def getInstance(cls, ibase):         try:             cls.__instance         except AttributeError:             cls.__instance = new (cls, ibase)         return cls.__instance  class StandardMathematicsSystem(MathematicsSystem):     def __init__(self, ibase):         if ibase.getBase() != new (IntegralNumber, 2):             raise NotImplementedError         self.base = ibase.getBase()      def calculateFactorial(self, target):         result = new (IntegralNumber, 1)         i = new (IntegralNumber, 2)         while i <= target:             result = result * i             i = i + new (IntegralNumber, 1)         return result  print StandardMathematicsSystem.getInstance(new (InternalBase, new (IntegralNumber, 2))).calculateFactorial(new (IntegralNumber, 6)) 

source http://gist.github.com/25049

vivek

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); }  

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).

S.Hoekstra

Example in C (C was tagged so i guess that's what you want) using recursion

unsigned long factorial(unsigned long f) {         if (f) return(f * factorial(f - 1));         return 1; }  printf("%lu", factorial(5)); 
Raj

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 efficent is to sum up logarhitms. If you use Log10 you get power and exponent.

Pseudocode

r=0 for i form 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 to much and thus decrease accuracy, but result suld be ok for even very large factorials.

Simple solution:

unsigned int factorial(unsigned int n) {    return (n == 1 || n == 0) ? 1 : factorial(n - 1) * n; } 

I would do this with a pre-calculated lookup table, as John said. 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];  } 

See for yourself!

**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(); } 
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!