除正常遞歸函數和循環方法之外,找到一個數的階乘的有效方法是什麼?由於常規方法花費的時間太長而無法產生輸出,因此有什麼方法可以比遞歸方法和循環方法減少時間複雜度?如果不是原因?查找因子的有效方法
回答
由於79!是1.711E98,你只需要79個數字的列表來使用查找表。 http://www.tsm-resources.com/alists/fact.html整數格式或在科學格式http://home.ccil.org/~remlaps/javascript/jstest1.html,所以它只是「剪切和粘貼」
查找表正是我所建議的。 –
但是我沒有看到他從哪裏得到79。通過我的計算(可能容易出現一個錯誤),對於32位整數,12個條目應該足夠了;對於64位,20,對於IEEE浮點數34和對於IEEE雙精度值170. –
如果你要計算多因子值,然後緩存值,你走是: 的階乘在列選項。
如果你只是一個單一的計算factorial(n)
,那麼循環可能是最好的,你可以得到。通過一些循環展開(一次計算兩次或四次乘法),你可能會從處理器中獲得更多的效果,但是它不太可能適用於非常大的階乘,因爲乘法本身就是一系列冗長的指令。
據我所知,沒有「神奇」的數學計算一個12 * 13 * 14 * 15
或類似的序列比乘以它們更快。
'gamma(i-1)== fact(i)'。計算'gamma'並不一定很簡單,但對於大型'i',它比單純乘法要快得多(並且你沒有得到你在循環中累積的舍入誤差:記住每次你得到一個舍入誤差,它乘以以下所有項)。 –
你只能得到浮點四捨五入的錯誤。浮點數不能超過幾百個左右。 –
約170,爲通常的'雙'。但是使用gamma也應該避免這個問題。 (我對「gamma」的計算方式不太瞭解,但快速瀏覽一下g ++庫的源代碼給人的印象是它比'O(n)'快得多,這就是循環的結果。 –
您可以使用Stirling's approximation來評估大因子。
當n進入1000的數字類型時,指數,對數等變得相當混亂,因爲它們超出了整數的數值範圍。 –
@MatsPetersson但任何擴展的精度/大小包應該已經擁有它們。使用這種或伽瑪函數的東西肯定會比循環更好,儘管它們在編程上顯然更加複雜。 –
由於您的某條評論說您想查找100000 !,因此此答案涵蓋了很多因子。
如果你並不需要一個確切的答案,你可以使用Stirling's Approximation
如果你想你需要使用一個任意精度的數學包像GMP arbitrary precision math package
我並不完全相信計算大指數和平方根等等,在大數學中更容易。我的天真的字符串數學方法目前進入12分鐘做100000!(10K相對容易,大約5秒鐘,但隨着數量變長,緩存不夠大,複製需要更長時間等等) –
使用ln(n!)= n * ln(n)-n形式對於n = 10000,我們得到ln(10000!)〜= 82103.所以10000! = = e^82103〜= 10^35657〜=(2^32)^ 3701(假設我的高中數學並沒有讓我失望)。所以很快得到一個非常粗略的近似值。我同意,如果你想要答案的所有35657數字,斯特林的是不是要走的路。但是現在我們知道我們可以使用GMP在〜3701 4字節的內存字中計算答案。 –
沒有,真的沒有一個確切的答案。如果您關心運行時成本,可以使用查找表(這需要您使用預先計算的值)來降低運行時成本。
要存儲每個因子可能需要太多的內存,所以讓我們存儲每個k:th因子。這需要程序在運行時執行多達k次的乘法運算。
比方說,您的運行時性能要求限制您爲每個階乘1000乘法。那麼你需要預先計算並存儲1000 !, 2000 !, 3000!等等直到你想要支持的上限(可用內存將限制你)。
因爲階乘函數快速變得比原生數據類型大,所以您需要一個可以處理大量數據的類。我假定它存在這樣一個類,它被稱爲BigInteger
。
BigInteger preCalculatedValues[] = { new BigInteger("1"), new BigInteger("<value of 1000!>"), and so on... }
BigInteger factorial(int n) {
int pre = n/1000;
int i;
if (pre > LARGEST_VALUE_HANDLED) {
// Either throw an exception or let it take longer. I choose to let it take longer.
pre = LARGEST_VALUE_HANDLED;
}
BigInteger result = preCalculatedValues[pre];
for (i = pre * 1000 + 1; i <= n; i++) {
result.multiplyWith(i); // This operation is probably overloaded on the * operator
}
}
計算非常大factorals的最簡單的方法是使用 伽瑪功能。另一方面:它不會像表查詢那樣快(如其他人所建議的那樣);如果您使用內置 的類型,你需要的表:
for 32 bits: 12 entries
for 64 bits: 20 entries
for float: 34 entries
for double: 170 entries
(有可能是一個錯誤上表中的關我寫 的代碼非常快速地計算出它們。)
對於double
和可能的float
,通常的循環方法 無論如何可能會引入太多舍入誤差。如果你 不想使用一個表,並且你有C++ 11, exp( lgamma( i + 1 ) )
應該做的伎倆。 (如果你不 有C++ 11,你可能有lgamma
功能無論如何,它是在C99 。)
如果你正在處理一些類型的延伸範圍類型的,你 可能必須實施lgamma
(和exp
)爲您的類型。
- 1. 查找的有效方法數的偶數因子的總數
- 2. 查找因子
- 3. 3查找值的有效方法int
- 4. 查找行索引的有效方法?
- 5. 找到數字的所有因素的最有效方法?
- 6. 查找視圖外部子視圖的有效方法
- 7. 查找共素數子陣列的有效方法
- 8. 查找子方法
- 9. 查找假數的所有因子
- 10. 查找數字的所有因子
- 11. 查找數字的因子
- 12. 確定b是否是一個因子的有效方法?
- 13. 查找大因子數的因數和?
- 14. 是否有更有效的方法來查找返回對象的子集?
- 15. Java因子方法
- 16. 查找因子總和
- 17. 查找兩組最大公共子集的有效算法?
- 18. 在R中找到子集的有效方法
- 19. 如何優化因子的查找因子
- 20. 尋找最近點的有效方法?
- 21. 查找經理的經理ID的有效方法
- 22. 查找多個RGB圖像的中值的有效方法
- 23. 有效的方法來查找ArrayList中的對象索引
- 24. 查找「表」中的值的有效方法C#
- 25. 最有效的方法來查找jQuery的
- 26. 查找元組數組中的邊界值的有效方法?
- 27. 查找跨多個數組的序列號的有效方法?
- 28. 查找double值的小數位數的有效方法
- 29. 查找和替換DataColumn中的值的有效方法
- 30. 素因子分解算法的效率
您試圖使用階乘來解決您的問題? – 2013-08-21 12:00:55
見http://www.luschny.de/math/factorial/FastFactorialFunctions.htm – Michael
你有多久? 'gmp'中的簡單實現可以在我的機器上以0.9秒完成(顯然,不同的處理器/機器將具有不同的性能)。 –