Thuật toán tốt nhất được biết đến là thể hiện giai thừa như một sản phẩm của các quyền lực chính. Người ta có thể nhanh chóng xác định các số nguyên tố cũng như công suất phù hợp cho từng số nguyên tố bằng cách sử dụng phương pháp sàng. Việc tính toán từng công suất có thể được thực hiện một cách hiệu quả bằng cách sử dụng bình phương lặp đi lặp lại, và sau đó các yếu tố được nhân lên với nhau. Điều này đã được Peter B. Borwein mô tả, về sự phức tạp của các yếu tố tính toán , Tạp chí thuật toán 6 376 Điện 380, 1985. ( PDF ) Tóm lại,có thể được tính trong thời gian , so với thời gian cần thiết khi sử dụng định nghĩa.n !O ( n ( nhật kýn )3đăng nhậpđăng nhậpn )Ω ( n2đăng nhậpn )
Điều mà sách giáo khoa có lẽ có nghĩa là phương pháp phân chia và chinh phục. Người ta có thể giảm các phép nhân bằng cách sử dụng mẫu thông thường của sản phẩm.n - 1
Đểbiểu thị là một ký hiệu thuận tiện. Sắp xếp lại các yếu tố của là
Bây giờ giả sử với một số nguyên . (Đây là một giả định hữu ích để tránh các biến chứng trong cuộc thảo luận sau đây và ý tưởng có thể được mở rộng thành chung .) Sau đóvà bằng cách mở rộng sự tái phát này,
Máy tính1 ⋅ 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 ⋯ ( 2 n - 1 )( 2 n ) ! = 1 ⋅ 2 ⋅ 3 ⋯ ( 2 n )
( 2 n ) ! = n ! ⋅ 2n⋅ 3 ⋅ 5 ⋅ 7 ⋯ ( 2 n - 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( 2tôi) ? = ( 22k- 1) Πi = 1k - 1( 2tôi) ? .
( 2k - 1) ?và nhân các sản phẩm một phần ở mỗi giai đoạn mất phép nhân. Đây là một cải tiến của hệ số gần từ phép nhân chỉ bằng cách sử dụng định nghĩa. Một số thao tác bổ sung được yêu cầu để tính toán sức mạnh của , nhưng trong số học nhị phân, điều này có thể được thực hiện với giá rẻ (tùy thuộc vào chính xác những gì được yêu cầu, nó có thể chỉ cần thêm một hậu tố số 0).
( k - 2 ) + 2k - 1- 222k- 222k- 1
Mã Ruby sau đây thực hiện một phiên bản đơn giản hóa này. Điều này không tránh tính toán lạingay cả khi nó có thể làm như vậy: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)
Ngay cả mã đầu tiên này cũng cải thiện tầm thường
f = 1; (1..32768).map{ |i| f *= i }; print f
khoảng 20% trong thử nghiệm của tôi.
Với một chút công việc, điều này có thể được cải thiện hơn nữa, đồng thời loại bỏ yêu cầu là sức mạnh của (xem phần thảo luận mở rộng ).2n2