Gdybyś musiał powtórzyć pętlę 7 razy, użyłbyś:
for (int i = 0; i < 7; i++)
lub:
for (int i = 0; i <= 6; i++)
Istnieją dwie kwestie:
- występ
- czytelność
Dla wydajności zakładam Java lub C #. Czy ma znaczenie, czy użyto „mniejszy niż” lub „mniejszy lub równy”? Jeśli masz wgląd w inny język, wskaż który.
Dla czytelności zakładam tablice oparte na 0.
UPD: Moja wzmianka o tablicach opartych na 0 może być myląca. Nie mówię o iterowaniu przez elementy tablicy. Tylko ogólna pętla.
Poniżej znajduje się dobry punkt na temat używania stałej, do której można by wyjaśnić, czym jest ta magiczna liczba. Więc gdybym miał " int NUMBER_OF_THINGS = 7
to" i <= NUMBER_OF_THINGS - 1
wyglądałoby dziwnie, prawda?
performance
conventions
readability
Eugene Katz
źródło
źródło
Odpowiedzi:
Pierwsza jest bardziej idiomatyczna . W szczególności wskazuje (w sensie zerowym) liczbę iteracji. Podczas korzystania z czegoś opartego na 1 (np. JDBC, IIRC) mógłbym ulec pokusie użycia <=. Więc:
Spodziewałbym się, że różnica w wydajności będzie nieznacznie mała w rzeczywistym kodzie.
źródło
Obie te pętle iterują 7 razy. Powiedziałbym, że ten z 7 jest bardziej czytelny / wyraźniejszy, chyba że masz naprawdę dobry powód do tego drugiego.
źródło
Pamiętam z moich czasów, kiedy robiliśmy 8086 Assembly na uczelni, było bardziej wydajne do zrobienia:
ponieważ była operacja JNS , która oznacza skok, jeśli nie ma znaku. Użycie tego oznaczało, że po każdym cyklu nie było przeszukiwania pamięci, aby uzyskać wartość porównawczą, ani porównania. Obecnie większość kompilatorów optymalizuje użycie rejestrów, więc kwestia pamięci nie jest już ważna, ale nadal uzyskuje się niepotrzebne porównanie.
Nawiasem mówiąc, wstawienie 7 lub 6 do pętli wprowadza „ magiczną liczbę ”. Dla lepszej czytelności powinieneś używać stałej z nazwą ujawniającą intencję. Lubię to:
EDYCJA: Ludzie nie rozumieją kwestii montażu, więc oczywiście wymagany jest pełniejszy przykład:
Jeśli zrobimy dla (i = 0; i <= 10; i ++), musisz to zrobić:
Jeśli zrobimy dla (int i = 10; i> -1; i--), to możesz uciec z tego:
Właśnie sprawdziłem i kompilator C ++ firmy Microsoft nie wykonuje tej optymalizacji, ale robi to, jeśli:
Więc morał jest taki, że jeśli używasz Microsoft C ++ †, a rosnąco lub malejąco nie robi różnicy, aby uzyskać szybką pętlę, powinieneś użyć:
zamiast któregokolwiek z tych:
Ale szczerze mówiąc, uzyskanie czytelności „for (int i = 0; i <= 10; i ++)” jest zwykle znacznie ważniejsze niż brak jednego polecenia procesora.
† Inne kompilatory mogą robić różne rzeczy.
źródło
7-i
co spowoduje zablokowanie wszelkich optymalizacji, które uzyskasz od liczenia wstecz.Zawsze używam <array.length, ponieważ jest łatwiejsza do odczytania niż <= array.length-1.
również mając <7 i biorąc pod uwagę, że wiesz, że zaczyna się od indeksu 0, powinno być intuicyjne, że liczba jest liczbą iteracji.
źródło
Z optymalizacyjnego punktu widzenia nie ma to znaczenia.
Z punktu widzenia stylu kodu, który preferuję <. Powód:
jest o wiele bardziej czytelny niż
także <od razu podaje liczbę iteracji.
Innym głosem za <jest to, że możesz zapobiec wielu przypadkowym pomyłkom.
źródło
@Chris, Twoje stwierdzenie, że .Długość jest kosztowna w .NET jest w rzeczywistości nieprawdą, aw przypadku prostych typów jest dokładnie odwrotnie.
jest faktycznie wolniejszy niż
Ta ostatnia to przypadek zoptymalizowany przez środowisko wykonawcze. Ponieważ środowisko wykonawcze może zagwarantować, że i jest prawidłowym indeksem tablicy, nie są wykonywane żadne kontrole ograniczeń. W pierwszym przypadku środowisko uruchomieniowe nie może zagwarantować, że nie zostałem zmodyfikowany przed zapętleniem i wymusza sprawdzanie granic tablicy przy każdym wyszukiwaniu indeksu.
źródło
.lenght
OR.size
. Nie jestem pewien, ale i nie jestem pewien, ale chcę się tylko upewnić.Nie ma to żadnego znaczenia, jeśli chodzi o wydajność. Dlatego użyłbym tego, co jest łatwiejsze do zrozumienia w kontekście problemu, który rozwiązujesz.
źródło
Wolę:
Myślę, że łatwiej to tłumaczy się na „powtarzanie pętli 7 razy”.
Nie jestem pewien wpływu na wydajność - podejrzewam, że wszelkie różnice zostałyby zestawione.
źródło
W Javie 1.5 możesz to zrobić
więc w przypadku tablicy nie musisz się martwić.
źródło
Myślę, że nie ma różnicy w wydajności. Druga forma jest jednak zdecydowanie bardziej czytelna, nie musisz mentalnie odejmować jednej, aby znaleźć ostatnią liczbę iteracji.
EDYCJA: Widzę, że inni się nie zgadzają. Dla mnie osobiście lubię widzieć rzeczywiste numery indeksów w strukturze pętli. Może dlatego, że bardziej przypomina
0..6
składnię Perla , która, jak wiem, jest równoważna(0,1,2,3,4,5,6)
. Jeśli widzę 7, muszę sprawdzić operator obok, aby zobaczyć, że w rzeczywistości indeks 7 nigdy nie został osiągnięty.źródło
Powiedziałbym, że używaj wersji "<7", ponieważ większość ludzi to przeczyta - więc jeśli ludzie będą przeglądać twój kod, mogą go źle zinterpretować.
Nie martwiłbym się, czy „<” jest szybsze niż „<=”, po prostu wybierz czytelność.
Jeśli chcesz zwiększyć prędkość, rozważ następujące kwestie:
Aby zwiększyć wydajność, możesz nieznacznie zmienić jego kolejność na:
Zwróć uwagę na usunięcie GetCount () z pętli (ponieważ będzie to sprawdzane w każdej pętli) i zmianę „i ++” na „++ i”.
źródło
W C ++ wolę używać
!=
, co jest możliwe do użytku ze wszystkimi kontenerami STL. Nie wszystkie iteratory kontenerów STL są mniej niż porównywalne.źródło
Edsger Dijkstra napisał artykuł na ten temat w 1982 roku, w którym argumentował za niższym <= i <górnym:
źródło
Po pierwsze, nie używaj 6 ani 7.
Lepiej używać:
W tym przypadku jest to lepsze niż używanie
Jeszcze lepiej (Java / C #):
A nawet lepiej (C #)
Pętla odwrotna jest rzeczywiście szybsza, ale ponieważ jest trudniejsza do odczytania (jeśli nie przez Ciebie innych programistów), lepiej jej unikać. Szczególnie w C #, Javie ...
źródło
Zgadzam się z tłumem, który mówi, że 7 ma sens w tym przypadku, ale dodam, że w przypadku, gdy 6 jest ważna, powiedz, że chcesz wyjaśnić, że działasz tylko na obiektach do szóstego indeksu, a następnie <= jest lepsze, ponieważ sprawia, że 6 jest łatwiejsze do zobaczenia.
źródło
Jeszcze na studiach pamiętam coś o tych dwóch operacjach, które były podobne pod względem czasu obliczeniowego procesora. Oczywiście rozmawiamy na poziomie montażu.
Jeśli jednak mówisz w języku C # lub Javie, naprawdę nie sądzę, aby jeden z nich był przyspieszeniem w stosunku do drugiego. Kilka nanosekund, które uzyskasz, najprawdopodobniej nie jest warte żadnego zamieszania, które wprowadzasz.
Osobiście napisałbym kod, który ma sens z punktu widzenia implementacji biznesowej i upewnić się, że jest łatwy do odczytania.
źródło
To bezpośrednio należy do kategorii „Poprawianie niewłaściwego wyglądu kodu” .
W językach indeksowania od zera, takich jak Java lub C #, ludzie są przyzwyczajeni do odmian
index < count
warunku. Tak więc wykorzystanie tej konwencji defacto sprawiłoby, że jeden błąd byłby bardziej oczywisty.Jeśli chodzi o wydajność: każdy dobry kompilator wart swojego zużycia pamięci powinien renderować bez problemu.
źródło
Na marginesie, gdy przeglądam tablicę lub inną kolekcję w .Net, znajduję
być bardziej czytelnym niż numeryczna pętla for. To oczywiście zakłada, że rzeczywisty licznik Int sam nie jest używany w kodzie pętli. Nie wiem, czy nastąpiła zmiana wydajności.
źródło
Istnieje wiele dobrych powodów, aby pisać i <7. Posiadanie liczby 7 w pętli, która powtarza się 7 razy, jest dobre. Wydajność jest faktycznie identyczna. Prawie każdy pisze i <7. Jeśli piszesz dla większej czytelności, użyj formularza, który wszyscy natychmiast rozpoznają.
źródło
Zawsze wolałem:
źródło
Nawyk używania <sprawi, że będzie on spójny zarówno dla Ciebie, jak i dla czytelnika podczas iteracji po tablicy. Każdemu będzie łatwiej mieć standardową konwencję. A jeśli używasz języka z tablicami opartymi na 0, to <jest konwencją.
To prawie na pewno ma większe znaczenie niż jakakolwiek różnica w wydajności między <i <=. Najpierw postaw na funkcjonalność i czytelność, a następnie zoptymalizuj.
Inną uwagą jest to, że lepiej byłoby mieć zwyczaj robienia ++ i zamiast i ++, ponieważ pobieranie i inkrementacja wymaga tymczasowości, a inkrementacja nie. W przypadku liczb całkowitych Twój kompilator prawdopodobnie zoptymalizuje tymczasowo, ale jeśli typ iteracji jest bardziej złożony, może nie być w stanie tego zrobić.
źródło
Nie używaj magicznych liczb.
Dlaczego jest 7? (lub 6 jeśli o to chodzi).
użyj właściwego symbolu dla numeru, którego chcesz użyć ...
W takim przypadku myślę, że lepiej jest użyć
źródło
Operatory „<” i „<=” mają dokładnie taki sam koszt wydajności.
Operator „<” jest standardowym i łatwiejszym do odczytania w pętli liczonej od zera.
Używanie ++ i zamiast i ++ poprawia wydajność w C ++, ale nie w C # - nie znam Javy.
źródło
Jak ludzie zauważyli, nie ma różnicy w żadnej z dwóch alternatyw, o których wspomniałeś. Aby to potwierdzić, wykonałem proste testy porównawcze w JavaScript.
Wyniki możesz zobaczyć tutaj . Nie jest z tego jasne, że jeśli zamieniam pozycję pierwszego i drugiego testu, to wyniki tych dwóch testów zamieniają się, jest to ewidentnie problem z pamięcią. Jednak trzeci test, w którym odwracam kolejność iteracji, jest wyraźnie szybszy.
źródło
Jak wszyscy mówią, zwyczajowo używa się iteratorów indeksowanych przez 0, nawet dla rzeczy poza tablicami. Jeśli wszystko zaczyna się na
0
i kończy się nan-1
, a dolne granice są zawsze,<=
a górne granice zawsze<
, to jest o wiele mniej myślenia, które musisz robić podczas przeglądania kodu.źródło
Świetne pytanie. Moja odpowiedź: użyj typu A („<”)
i < strlen(s)
a nie indeks ostatniego elementu, więc jednolitość jest ważna.Inny problem dotyczy całej tej konstrukcji.
i
pojawia się w nim 3 razy , więc można go pomylić. Konstrukcja pętli for mówi, jak zrobić, a nie co robić . Proponuję przyjąć to:BOOST_FOREACH(i, IntegerInterval(0,7))
Jest to bardziej przejrzyste, kompiluje się dokładnie takie same instrukcje asm, itp. Zapytaj mnie o kod IntegerInterval, jeśli chcesz.
źródło
Tyle odpowiedzi ... ale wydaje mi się, że mam coś do dodania.
Wolę, aby liczby dosłowne były wyraźnie widoczne jakie wartości „i” przyjmie w pętli . Tak więc w przypadku iteracji przez tablicę od zera:
for (int i = 0; i <= array.Length - 1; ++i)
A jeśli po prostu zapętlasz, a nie iterujesz po tablicy, liczenie od 1 do 7 jest całkiem intuicyjne:
for (int i = 1; i <= 7; ++i)
Czytelność ma przewagę nad wydajnością, dopóki jej nie sprofilujesz, ponieważ prawdopodobnie nie wiesz, co kompilator lub środowisko wykonawcze zrobi z Twoim kodem do tego czasu.
źródło
Możesz także użyć
!=
zamiast tego. W ten sposób otrzymasz nieskończoną pętlę, jeśli popełnisz błąd podczas inicjalizacji, co spowoduje wcześniejsze zauważenie błędu, a wszelkie problemy, które spowoduje, będą ograniczone do utknięcia w pętli (zamiast mieć problem znacznie później i nie znajdując to).źródło
Myślę, że jedno lub drugie jest w porządku, ale kiedy już wybierzesz, trzymaj się jednego lub drugiego. Jeśli jesteś przyzwyczajony do używania <=, spróbuj nie używać <i na odwrót.
Wolę <=, ale w sytuacjach, w których pracujesz z indeksami zaczynającymi się od zera, prawdopodobnie spróbuję użyć <. Jednak to wszystko zależy od osobistych preferencji.
źródło
Ściśle z logicznego punktu widzenia, musisz pomyśleć, że
< count
byłoby to bardziej wydajne niż<= count
z tego dokładnego powodu, który<=
będzie testował również pod kątem równości.źródło