首頁  >  問答  >  主體

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中文网2715 天前717

全部回覆(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
  • 取消回覆