Porównanie czasu trwania silni

0

Witam, mam taki krótki kod i zastanawia mnie czemu program liczy silnie z większej liczby szybciej niż z mniejszej ?

public class silnia {


    private static long start_silniaCzesc;
    private static long start_silnia1;
    
    static int silnie( int liczba)
    {                 
        if ( liczba == 0)
            return 1;
        
        else
            return liczba*silnie(liczba - 1);            
    }
            
    public static void main(String[] args) 
    {
                    
        start_silniaCzesc = System.nanoTime();
        int temp1 = silnie(2);
        System.out.println("Time ( rekurencyjnie) : "  +(System.nanoTime() - start_silniaCzesc)*0.000001+ "ms");
        System.out.println("Wynik: " + temp1);
                                                             
        start_silnia1 = System.nanoTime();        
        int temp= silnie(12);
        System.out.println("Time ( rekurencyjnie) : "  +(System.nanoTime() - start_silnia1)*0.000001+ "ms");
        System.out.println("Wynik: " + temp);
                
        }

}

Mógłby mi ktoś pokazać gdzie tu jest błąd ? silnia (12) oblicza się rząd wielkości szybciej niż silnia(2)..

0

A teraz w main zamień ich kolejność, najpierw policz silnie z 12 a później z 2.

2

Po szybkiej analizie wychodzi na to, że jeżeli robisz coś takiego:

System.out.println("Time ( rekurencyjnie) : "  +(System.nanoTime() - start_silnia1)+ "ms");

czyli podczas wypisywania sprawdzasz aktualny czas to dla pierwszego wypisania czas jest znacznie większy, nawet po usunięciu jakiejkolwiek silni! Sprawę naprawiło (mniej więcej) dodanie takiej zmiennej jak masz na początku która bierze czas i wzięcie czasu zaraz przed wypisaniem:

zmienna = System.nanoTime();
System.out.println("Time ( rekurencyjnie) : "  +(zmienna - start_silnia1)+ "ms");
0

@mikhal wydaje się, że teraz mierzy dobrze, popatrz sobie jak to wygląda dla jednej pętli i drugiej która jest 2 razy dłuższa, czas wychodzie też 2 razy dłuższy. To, że czasy dla silni takie wyszły jakie wyszły to wina tego, że dla komputera pomnożenie 2 liczb to prosta sprawa a różnica w ilości mnożeń między tymi dwoma silniami jest niewielka, przy pierwszej 2 mnożenia przy drugiej 12.

0

Rzeczywiście, jest trochę lepiej ale myślałem, że te różnice w czasie będą bardziej widoczne. Robię właśnie program, który jakby dzieli obliczenie silni na części(wątki), czyli np. mam obliczyć silnie(12) to liczę silnie(6) - (123456) i (789101112), tylko to mnie zastanawia, że są bardzo małe różnice w czasie... np. obliczając silnia(12) czas: 0.004226ms , silnie(6/2) czas: 0.00483ms , silnie(6)/silnie(6/2) czas: 0.00483ms, czyli tutaj racja- zależy to od liczby mnożeń. Tylko jak ja mam teraz pokazać prowadzącemu, że rozdzielając to na wątki uzyskam skrócenie czasu?
bo (7891011*12) dodatkowo dzielę co też czas rośnie dzięki temu w wyrażeniu -> silnie(6)/silnie(6/2)

1

Nie zwiększysz wydajności rozdzielając na wątki tak krótką operację. Silnia to co najwyżej kilkaset cykli procesora, a samo utworzenie wątku to kilka- albo i kilkadziesiąt tysięcy cykli.

1

Liczenie silni jako przykład użycia wątków jest generalnie OK. Trzeba to tylko "ociupinkę" skomplikować. Moja propozycja jest następująca:

  1. Liczymy naprawdę "dużą" silnię np. 99!
  2. Używamy do tego BigDecimal/BigInteger (long ma zakres tylko 2^63-1, a tu mamy wynik rzędu 10/\155).
  3. wprowadzamy logikę odpowiedzialną za podział operacji na wiele wątków. Przykładowo określasz, że wątek nie powinien wykonać więcej niż 15 mnożeń. Dzielisz zadanie na tyle wątków by nie przekroczyć tej granicy. Odpalasz via ServiceExecutor.
0

Jeśli silnie zamieścisz w pętli wykonującej się np. 10 000 razy to różnica pomiędzy wynikami jest znaczna.

1 użytkowników online, w tym zalogowanych: 0, gości: 1