Nie rozumiem... logiki.

Nie rozumiem... logiki.

Wątek przeniesiony 2020-12-07 00:49 z Off-Topic przez cerrato.

AF
  • Rejestracja: dni
  • Ostatnio: dni
0
jarekr000000 napisał(a):

@cerrato:

Żadne pętlnie nie są intuicyjne. One są zrozumiałe tylko dla maszyn, a ludzie pracując w kulawych językach programowania nauczyli się je rozumieć (musieli).
Matematycy na pętle generalnie nie wpadli (!!!) - w większości działów matematyki nie ma czegoś takiego jak zmieniający się stan zmiennej (licznik pętli choćby).

Matematycy tak samo musieli wymyślić pętlę, nieskończoną również, tak jak i coś na kształt wyjątku do zawieszenia programu. W ogóle mówienie o braku zmiany stanu w matematyce jest zabawne, gdy cała teoria obliczeń jest oparta o maszynę Turinga, która to modyfikuje stan w miejscu.

renderme
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1520
2

To nie tak źle, że jej nie rozumiesz. Może dzięki temu będziesz miał pokorę i będziesz dążył do czystego kodu.

Kiedyś byłem świadkiem jednej rekrutacji juniorskiej i padły tam słowa: "to zły kandydat. Jest zbyt inteligentny na wiedzę którą ma i może coś zepsuć. Robi spaghetti, bo je rozumie".
Pielęgnuj to, że brzydzisz się zagnieżdzeń, zapętleń - czasami są nieuniknione, ale nie brnij w nie, jak nie musisz.

Ps. To nie jest reguła, ale zwykle takie chamskie zagnieżdzenia for, poza jakąś skrajną optymalizacją nie są dobrą praktyką. Zwykle lepiej już wywołać funkcje/metodę, w której jest kolejne zagnieżdzenie.

Silv
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Warszawa
1
przeh napisał(a):

(…) przez rozumowanie logiczne rozumiem łączenie ze sobą faktów, a w tym przypadku zmiennych. Nie rozumiem jednak dodawania przed pętlą albo w pętli jakiejś abstrakcyjnej zmiennej, która jest pusta, żeby później w iteracji trzeba było do niczego dodać coś.

Hm… rozumiem.

Co do mnie, nie pamiętam, czy miałem jakieś problemy z pętlami, czy nie, gdy zaczynałem naukę programowania. Aktualnie idę w stronę rekurencji, ale polecać Ci jej nie będę. Nadal mam z tyłu głowy, że łatwiej w niej popełnić w niej błąd (logiczny) niż w takiej zwykłej pętli. Choć przyznam, że tego problemu, o którym napisałeś, nie ma wydaje się nie być w funkcjach korzystających z rekurencji – przynajmniej w znanych mi językach.

Może dobrym punktem wyjścia będą dla Ciebie funkcje typu forEach czy map (obecne np. w JavaScript'cie). Operują one na "kolekcjach" – wykonują daną operację raz dla każdego elementu kolekcji. Są one bardziej intuicyjne od rekurencji oraz zwykłej pętli według mnie. Czasem też łatwiej pisać za ich pomocą kod zwięzły logicznie.

piotrpo
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 3303
2

Dobre, autor pisze, że nie kuma pętli a wy o matematyce, składni konkretnych języków i nie wiadomo czym jeszcze... Spróbuję po swojemu.
Problem:
Czasami pisząc program trzeba wykonać jakiś kawałek kodu więcej niż 1 raz. Żeby nie utknąć w samym algorytmie przykład kompletnie abstrakcyjny - mamy wypisać wszystkie liczby z przedziału 0..9. kod wyglądałby tak:

Kopiuj
drukuj 0
drukuj 1
drukuj 2
drukuj 3
drukuj 4
drukuj 5
drukuj 6
drukuj 7
drukuj 8
drukuj 9

To co widać wyżej zadziała, ale trzeba pisać dużo kodu, co z jednej strony jest czasochłonne, z drugiej łatwo się pomylić, a czasami będzie niemożliwe (np. dla przedziału 0..1000000).
Żeby jakoś rozwiązać te niedogodności, języki programowania odpowiadają na tę potrzebę poprzez umożliwienie zapętlania kodu, w najprostszym wydaniu wygląda to tak:

Kopiuj
licznik := 0 //przypisz licznikowi wartość 0

#hop //po prostu miejsce w kodzie, oznaczenie miejsca, do którego program może skoczyć
drukuj licznik
licznik := licznik + 1 //zwiększ wartość licznika o 1
jeżeli licznik <= 9 to skocz do #hop

Czyli mamy kod do wykonania, jakiś warunek i jeżeli ten warunek jest spełniony, to program ma skoczyć w określone miejsce (cofnąć się do początku bloku pętli. W "normalnym" kodzie można do tego użyć pętli for:

Kopiuj
for(<coś co ma być wykonane przed wejściem w pętlę>; <warunek skoku>; <coś co ma być wykonane po każdym skoku>){
  <instrukcje, które maja być wykonane w każdym przebiegu pętli>
}

Czyli właściwy kod, przy użyciu pętli for będzie wyglądał tak:

Kopiuj
for(int licznik = 1; licznik <=9; licznik = licznik +1){
  print(licznik);
}

Teraz zmieńmy zadanie - wypiszmy każdą możliwą kombinację cyfr 0..9: 0-0, 0-1 ... 9-9. Zrobimy to dzięki temu, że częścią instrukcji wykonywanych w pętli może być kolejna pętla:

Kopiuj
for(int licznik = 1; licznik <=9; licznik = licznik +1){
  for(int drugiLicznik = 0; drugiLicznik <= 9; drugiLicznik = drugiLicznik + 1){
     print(licznik+"-"+drugiLicznik);
  }
}

W każdym z 10 przebiegów głównej pętli wykonywane jest 10 przebiegów pętli wewnętrznej i to jest cała tajemnica "podwójnej pętli". Warto pamiętać, że pętle nie mogą się "przecinać". Dodatkowo, oprócz pętli for z licznikiem mogą być używane inne konstrukcje: while, do..while, które czasami pozwalają na prostsze zapisanie konkretnych algorytmów.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.