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.