2016-11-07 130 views
1

我有一个函数可以计算阶乘和组合如下。对于一个非常大的数字计算

int faktorial(int n) 
    { 
     if((n == 0)||(n == 1)) 
     { 
      return (1); 
     } 
     else 
     { 
      return (n * faktorial(n-1)); 
     } 
    } 

    int Kombinasi(int x, int y) 
    { 
     int n = faktorial(x); 
     int k = (faktorial(x - y)) * (faktorial(y)); 
     int hasil = n/k; 
     return (hasil); 
    } 

但是在计算阶乘时存在一个问题。 假设我想计算x = 1000和y = 4的组合函数。现有函数的调用阶乘函数。但阶乘函数不能计算它们。如何解决这个问题呢 ?。抱歉,我的英语很不好。谢谢。

+1

外表到[BigInteger的](https://msdn.microsoft.com/en-us/library/system.numerics.biginteger(V = vs.110)的.aspx)类 – Jonesopolis

+2

阶乘为1000是一个很大的数字,您需要添加数字命名空间并使用bigInteger类,使用算法计算1000的阶乘可能需要很长时间,也许使用记忆或其他方法可以提高计算效率 – Overmachine

+0

如果您有兴趣非递归阶乘计算机,你可以在这里查看我的库的[this part](https://github.com/spearson/xofz.Core/blob/master/xofz.Core/Framework/Computation/FactorialComputer.cs)。 –

回答

1

首先,要回答你的问题 - 你可以处理更大的值(最大为2^64 - 1)如果你使用

ulong c; 

二,一点点的帮助 - 不会帮助你的锻炼。即使是无符号的long也不能处理这样大的值。但是,请注意,相反,要获得(n选择k),可以简单地计算(n *(n-1)* .... *(n-k + 1))/ k! 。

+0

'unsigned long'不是C#中的一种类型。 – Kyle

+0

@凯尔老习惯难改。编辑。 – matanso

2

BigInteger作品,并在1000年相当快!

BigInteger faktorial(BigInteger n) 
{ 
    if ((n == 0) || (n == 1)) 
    { 
     return (1); 
    } 
    else 
    { 
     return (n * faktorial(n - 1)); 
    } 
} 

BigInteger Kombinasi(BigInteger x, BigInteger y) 
{ 
    BigInteger n = faktorial(x); 
    BigInteger k = (faktorial(x - y)) * (faktorial(y)); 
    BigInteger hasil = n/k; 
    return (hasil); 
} 

答:

4023872600770937735437024339230039857193748642107146325437999104299385123986290205920442084869694048004799886101971960586316668729948085589013238296699445909974245040870737599188236277271887325197795059509952761208749754624970436014182780946464962910563938874378864873371191810458257836478499770124766328898359557354325131853239584630755574091142624174743493475534286465766116677973966688202912073791438537195882498081268678383745597317461360853795345242215865932019280908782973084313928444032812315586110369768013573042161687476096758713483120254785893207671691324484262361314125087802080002616 831510273418279777047846358681701643650241536913982812648102130927612448963599287051149649754199093422215668325720808213331861168115536​​1583654698404670897560290095053761647584772842188967964624494516076535340819890138544248798495995331910172335555660213945039973628075013783761530712776192684903435262520001588853514733161170210396817592151090778801939317811419454525722386554146106289218796022383897147608850627686296714667469756291123408243920816015378088989396451826324367161676217916890977991190375403127462228998800519544441428201218736174599264295658174662830295557029902432415318161721046583203678690611726015878352075151628422554026517048330422614397428693306169089796848259012545832716822645806652676995865268227280707578139185817888965220816434834482599326604336766017699961283186078838615027946595513115655203609398818061213855860030143569452722420634463179746059468257310379008402443243846565724501440282188525247093519062092902313649327349756551395872055965422874977401141334696271542284 5862377387538230483865688976461927383814900140767310446640259899490222221765904339901886018566526485061799702356193897017860040811889729918311021171229845901641921068884387121855646124960798722908519296819372388642614839657382291123125024186649353143970137428531926649875337218940694281434118520158014123344828015051399694290153483077644569099073152433278288269864602789864321139083506217095002597389863554277196742822248757586765752344220207573630569498825087968928162753848863396909959826280956121450994871701244516461260379029309120889086942028510640182154399457156805941872748998094254742173582401063677404595741785160829230135358081840096996372524230560855903700624271243416909004153690105933983835777939410970027753472000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

注意,但是,它似乎溢出上面大约8889!以上的堆栈。

1

由于看起来您真正想要做的是计算二项式系数,因此使用BigInteger的替代方法是利用阶乘的一些数字属性。因此,而不是直接计算阶乘(可以是大的),可以改为做到这一点:

long Kombinasi(long x, long y) 
{ 
    if(y == 0) return 1; 
    return (x * Kombinasi(x - 1, y - 1))/y; 
} 

您也可以使用这种算法结合BigInteger如果你需要更大的价值:

BigInteger Binomial(BigInteger n, BigInteger k) 
{ 
    if(k <= 0) return 1; 
    return (n * Binomial(n - 1, k - 1))/k; 
} 

这将比计算阶乘和分裂更有效率,因为它利用了大部分阶乘项抵消的事实。它也将执行更少的乘法,特别是如果k很小。

0

正如其他成员所建议我们可以使用BitInteger作为大数字。 我不知道它是否有用,但我想在此解释一点。

所以让我们说我们有一个有很大价值的signed int(int.Max)和如果你尝试添加一些正整数值(10),它不会给你System.OverflowException。它只是给你消极的价值。所以如果你想在这种情况下引发异常。您可以使用checked关键字。如果表达式产生的值超出了目标类型的范围。如果表达式包含一个或多个非常量值,则编译器不会检测到溢出。溢出检查可以通过使用checked关键字来启用。所以当你尝试上面提到的东西时,它会抛出异常,你可以相应地处理它。

checked in C#

相关问题