Bilinen en iyi algoritma, faktörlüğü en büyük güçlerin bir ürünü olarak ifade etmektir. Bir elek yaklaşımı kullanarak her bir astar için primerlerin yanı sıra doğru gücü de hızlı bir şekilde belirleyebilirsiniz. Her bir gücün hesaplanması, tekrarlanan kareler kullanılarak verimli bir şekilde yapılabilir ve ardından faktörler birlikte çarpılır. Bu, Peter B. Borwein, Faktörlerin Hesaplanmasının Karmaşıklığı Üzerine, Algoritmalar Dergisi 6 376-380, 1985'te tarif edilmiştir. ( PDF ) Kısacası,olarak hesaplanabilmektedir ile karşılaştırıldığında zaman, tanımı kullanıldığında süre gereklidir.n!O(n(logn)3loglogn)Ω(n2logn)
Ders kitabının belki de anlamı, böl ve yönet yöntemiydi. Biri , ürünün normal desenini kullanarak çarpımlarını azaltabilir .n−1
Bırakgöstermektedirler uygun bir gösterim olarak. faktörlerini yeniden düzenleyin olarak
Şimdi, tamsayısı için olduğunu varsayalım . (Bu, aşağıdaki tartışmadaki komplikasyonlardan kaçınmak için yararlı bir varsayımdır ve fikir genel genişletilebilir .) Sonrave bu nüksü genişleterek,
Hesaplama1 ⋅ 3 ⋅ 5 ⋯ ( 2 n - 1 ) ( 2 n ) ! = 1 ⋅ 2 ⋅ 3 ⋯ ( 2 n ) ( 2 n ) ! = n ! ⋅ 2 n ⋅ 3 ⋅ 5 ⋅ 7 ⋯ ( 2 n - 1 ) . n = 2 k k >n?1⋅3⋅5⋯(2n−1)(2n)!=1⋅2⋅3⋯(2n)
(2n)!=n!⋅2n⋅3⋅5⋅7⋯(2n−1).
n=2kn ( 2 k ) ! = ( 2 k - 1 ) ! 2 2 k - 1 ( 2 k - 1 ) ? ( 2 k ) ! = ( 2 2 k - 1 + 2 k - 2 + ⋯ + 2 0 ) k - 1 ∏ i = 0 ( 2 i )k>0n(2k)!=(2k−1)!22k−1(2k−1)?( 2 k - 1 ) ? ( k - 2 ) + 2 k - 1 - 2 2 2 k - 2 2 2 k - 1(2k)!=(22k−1+2k−2+⋯+20)∏i=0k−1(2i)?=(22k−1)∏i=1k−1(2i)?.
(2k−1)?ve kısmi ürünlerin her aşamada çoğaltılması çarpımını alır. Bu, yaklaşık bir faktör bir gelişmedir den , sadece tanım kullanılarak çarpma. gücünü hesaplamak için bazı ek işlemler yapılması gerekir , ancak ikili aritmetik işleminde bu ucuza yapılabilir (tam olarak neyin gerekli olduğuna bağlı olarak, sadece sıfır eki eklemek gerekebilir ).
( k - 2 ) + 2k - 1- 222k- 222k- 1
Aşağıdaki Ruby kodu, bunun basitleştirilmiş bir versiyonunu uygular. Bu yeniden hesaplama engellemezyapabildiği yerlerde bile:n ?
def oddprod(l,h)
p = 1
ml = (l%2>0) ? l : (l+1)
mh = (h%2>0) ? h : (h-1)
while ml <= mh do
p = p * ml
ml = ml + 2
end
p
end
def fact(k)
f = 1
for i in 1..k-1
f *= oddprod(3, 2 ** (i + 1) - 1)
end
2 ** (2 ** k - 1) * f
end
print fact(15)
Bu ilk-geçiş kodu bile önemsizliği arttırıyor
f = 1; (1..32768).map{ |i| f *= i }; print f
Testimde yaklaşık% 20 oranında.
Çalışma ile biraz, bu aynı zamanda şartının kaldırılması, daha da geliştirilebilir bir güç olmak (bkz yoğun tartışma ).2n2