C# Dlaczego dzielenie jest wolniejsze niż mnożenie?

W językach programowania, a konkretnie w C#, można wykonać 4 operacje arytmetyczne: dodawanie, odejmowanie, mnożenie i dzielenie.

Z zewnątrz może się wydawać, że wszystkie są podobne pod względem wydajności, ale okazuje się, że jeden z nich jest znacznie wolniejszy w porównaniu do pozostałych 3.

Który z nich jest wolniejszy, możesz zapytać? Podział.

Według tego papieru HP:

Dzielenie zmiennoprzecinkowe i pierwiastek kwadratowy zajmują znacznie więcej czasu niż dodawanie i mnożenie. Te dwa ostatnie są obliczane bezpośrednio, podczas gdy pierwsze są zwykle obliczane za pomocą algorytmu iteracyjnego. Najbardziej powszechnym podejściem jest użycie iteracji Newtona-Raphsona bez dzielenia w celu uzyskania przybliżenia odwrotności mianownika (dzielenie) lub odwrotności pierwiastka kwadratowego, a następnie pomnożenie przez licznik (dzielenie) lub argument wejściowy (pierwiastek kwadratowy)..

Aby zweryfikować powyższe stwierdzenie, zdecydowałem się przeprowadzić prosty test, korzystając z poniższego kodu:

        //Generate two random numbers
        var rand = new System.Random();
        float a = rand.Next();
        float b = rand.Next();

        Debug.Log("Number a: " + a + " Number b: " + b);

        System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();

        watch.Start();
        //Addition
        for (int i = 1; i < 1000000; i++)
        {
            float tmp = a + b;
        }
        watch.Stop();
        //Output
        Debug.Log("Addition took: " + watch.Elapsed.TotalSeconds.ToString("0.0000") + " seconds");

        watch.Reset();
        watch.Start();
        //Subtraction
        for (int i = 1; i < 1000000; i++)
        {
            float tmp = a - b;
        }
        watch.Stop();
        //Output
        Debug.Log("Subtraction took: " + watch.Elapsed.TotalSeconds.ToString("0.0000") + " seconds");

        watch.Reset();
        watch.Start();
        //Multiplication
        for (int i = 1; i < 1000000; i++)
        {
            float tmp = a * b;
        }
        watch.Stop();
        //Output
        Debug.Log("Multiplication took: " + watch.Elapsed.TotalSeconds.ToString("0.0000") + " seconds");

        watch.Reset();
        watch.Start();
        //Division
        for (int i = 1; i < 1000000; i++)
        {
            float tmp = a / b;
        }
        watch.Stop();
        //Division
        Debug.Log("Division took: " + watch.Elapsed.TotalSeconds.ToString("0.0000") + " seconds");

Zasadniczo przeprowadziłem milion dodawania, odejmowania, mnożenia i dzielenia dla dwóch losowych liczb i zmierzyłem czas potrzebny na przetworzenie każdej z nich. Test powtórzono 5 razy i oto wynik:

  • Dodawanie trwało średnio 0,0004 sekundy
  • Odejmowanie trwało średnio 0,0003 sekundy
  • Mnożenie trwało średnio 0,0003 sekundy
  • Dzielenie trwało średnio 0,0044 sekundy

Wynik pokazał, że dodawanie, odejmowanie i mnożenie są podobne pod względem wydajności, ale dzielenie wydaje się być około 1100% wolniejsze.

Niewielka różnica, która prowadzi do wniosku, że zawsze, gdy to możliwe, lepiej jest zastosować mnożenie zamiast dzielenia. Na przykład, jeśli chcesz podzielić liczbę przez 2, najlepiej pomnożyć ją przez 0,5.

Sugerowane artykuły
Dlaczego pierwiastek kwadratowy jest powolną operacją w języku C#?
Wprowadzenie do C#
Przewodnik po pisaniu i odzyskiwaniu danych z kodu wielowątkowego w języku C#
Wskazówki dotyczące znalezienia wymarzonej pracy dla aspirujących programistów C#
Jak nauka języka C# może pomóc w spłacie długu
Obsługa strumieni danych oktetowych w języku C#
Co to jest C#?