final long maxK = Math.min(K, N - K); for (long i = 1L; i <= maxK; i++) result = result.multiply(BigInteger.valueOf(N - i + 1L)).divide(BigInteger.valueOf(i));
return result; }
Ta druga metoda jest efektywna czasowo i pamięciowo, jest tylko około trzy razy wolniejsza od wersji poprzedniej. W obu metodach sprawdzane są przypadki szczególne oraz zoptymalizowano liczbę pętli dla korzystając z faktu, że funkcja ta jest symetryczna.
Przykładowy predykat w Prologu:
silnia(0, 1) :- !. silnia(1, 1) :- !. silnia(N, X) :- N1 is N-1, silnia(N1, X1), X is N * X1.
npok(N, K, X) :- silnia(N, X1), silnia(K, X2), NK is N-K, silnia(NK, X3), X is X1 / (X2 * X3).
Procedura ta działa szybko i z minimalnym kosztem pamięciowym – wymaga tylko dwu pomocniczych zmiennych (a po dodatkowym usprawnieniu nie potrzebowałaby żadnych). Drobną wadą tego sposobu jest niewielki nadmiar w trakcie obliczeń: maksymalna wartość pośrednia, otrzymana przed ostatnim dzieleniem przez jest -krotnie większa od ostatecznego wyniku.