ホームページ  >  に質問  >  本文

c++ - 特林斯公式如何计算N! 的最高位

如果是一个非常大的N <10000000 那么计算出来的N!也是非常大的,现在只需要知道最高位的数字。
通过斯特林公式可以计算。
特林斯公式:
(公式1)
如下是算法:

result = 0.5* log(2*PI*(double)n)/log(10.0) + (double)n* log((double)n/E)/log(10.0);
result -= (int)result;
first_number = exp(result * log(10.0));

以上算法代码计算通过公式表示:
(公式2)
目前已知通过如下计算可以得到最高位:
(公式3)
剩下的就是求N!,虽然N!可以通过特林斯计算,但是计算结果非常大。计算机直接计算会溢出结果,如下执行结果:

可以看出当执行到180的时候结果都已经溢出。
原因应该是在计算N! 的时候结果直接存储在计算机导致空间不足。
我所不明白的是为什么(公式2)的算法就可以直接计算出结果不溢出,且正确(当然数字过小的话也会有错误,比如0,1,2,3,7,8结果将不正确)。

PHP中文网PHP中文网2765日前754

全員に返信(2)返信します

  • 迷茫

    迷茫2017-04-17 13:57:29

    最终是通过以10为底的对数log10(xxx)来求其最高位,这个你理解吧?他上面就是通过对数变换把求以10为底的对数转为以e为底的对数 aka: ln(yyy)

    返事
    0
  • ringa_lee

    ringa_lee2017-04-17 13:57:29

    首先,胡须佬头,已经说的很明白了,原理就是他所说的那个,把原来用lg去求的问题,转换为了ln去求。

    我还是给你贴张tu吧:(喜欢数学的都是好样的)

    看到啦,其实上面已经验证过了,如果要求5014的最高位,那么可以写成:
    最高位 = 5014 / (取整数)1g(5014); (注意类C语言里面,除法,会进行整型截断)

    ok,再说正事儿,你那个特林斯公式,假设拿到的阶乘的近似值为X (一大串不管了,简单点儿叫X),

    如果想拿到这个数的最高位h,那么有如下计算:

    h = X / (int)lgX;

    此时,通过特林斯公式,X 已求得,

    计算一下“lgX的整数部分”就可以了。

    先笼统的算(先不求整部和小数部分,直接算lgX)

    lgX = lnX / ln10 (就是你上面把特林斯公式带进去求值的那个式子,哦,你的图还算错了)
    得到lgX= result (我化简过了,不信你把那个特林斯公式化简成)

    到这里,就明白了,拿到result的整数部分,就能救出lgX的整数部分了,也就能求出最高位h.

    而不是你说的“拿到小数部分”。

    最后,根据你提供的特林斯公式,得到阶乘factorial的值为:
    X 约等于 e^(ln10 * result的整数部分); (你可以自己从特林斯的公式变形到这一步看看)

    貌似也不是你所说的
    first_number = exp(result * log(10.0));

    再有问题,在讨论?贴出你最终的结果?

    返事
    0
  • キャンセル返事