Pętle warunkowe while i repeat
Pętla while(…){…}
Składnia pętli while(…){…} wygląda następująco:
while (warunek) { instrukcja zmieniająca warunek
instrukcja 1
instrukcja 2
…
instrukcja n}
Działa ona podobnie działa podobnie, jak pętla for(…){…}, ale jest bardziej uniwersalna. Oznacza to, że w każdym programie pętlę for(…){…} można zastąpić pętlą while(…){…}, ale są sytuacje, gdy pętli warunkowych nie można zastąpić iteracją. Dzieje się tak wtedy, gdy liczby “obrotów” pętli nie można z góry przewidzieć.
Przykładem zastąpienia pętli for(…){…} pętlą while(…){…} jest program pokazany w poprzednim rozdziale powodujący 10-krotne wyświetlenie się napisu “Hallo world!”.
> i=1 > while (i <= 10) { cat("Hello World!\n") + i=i+1 } Hello World! Hello World! Hello World! Hello World! Hello World! Hello World! Hello World! Hello World! Hello World! Hello World! |
Brak iteracji spowodował, że najpierw utworzono obiekt i potem nadano mu wartość początkową. Potem pojawił się warunek i <= 10, a wśród instrukcji było przypisanie i=i+1. Te elementy były konieczne do tego, by pętla zakończyła się. Stosowanie pętli iteracyjnej jest krótsze i bezpieczniejsze. Gdyby przez pomyłkę napisano warunek i <= -10 albo i = i-1, uruchomiony program trwałby i trwał. Zablokowałby wszystkie działania w R. Wtedy należałoby kliknąć w górnym menu na “Różne” a następnie “Przerwij bieżące obliczenia” albo nacisnąć klawisz Esc.
Gdy nie potrafimy przewidzieć krotności powtórzeń wykonania napisu musimy zastosować pętlę while(…){…}. Przykładowo funkcja samlple(5,1) oznacza wylosowanie jednej liczby ze zbioru {1,2,3,4,5}. W R losowanie liczby z ciągów 1:n uzyskuje się za pomocą funkcji sample(n,1). Jeżeli z pewnych powodów wymagane jest wykonywanie napisu, dopóki nie zostanie wylosowana liczba 5, to należy napisać:
> i=1 > while (i != 5) { cat("Hello World!\n") + i=sample(5,1) } Hello World! Hello World! Hello World! Hello World! Hello World! |
Przykładem programu, w którym pętla while(…){…}, nie może zostać zastąpiona pętlą for(…){…} jest program wyliczający największy wspólny mianownik dwóch liczb całkowitych metodą Euklidesa. Algorytm ten polega na dzieleniu liczby większej przez mniejszą, a następnie zastępowaniu liczby większej mniejszą, a mniejszej resztą z dzielenia. Proces ten jest powtarzany aż do uzyskania reszty zerowej. Program wygląda bardzo prosto:
a = 12528 b = 144288 c = 1 while (c != 0) { c = b %% a b = a a = c} cat("Największy wspólny podzielnik = ",b,"\n") |
Po skopiowaniu go do konsoli uzyskamy:
> a = 12528 > b = 144288 > c = 1 > while (c != 0) { + c = b %% a + b = a + a = c} > cat("Największy wspólny podzielnik = ",b,"\n") Największy wspólny podzielnik = 432 |
Pętla repeat{…}
Składnia pętli repeat wygląda następująco:
repeat { instrukcja 1
instrukcja 2
…
instrukcja n}
Pętla repeat{…} pozornie nie jest pętlą warunkową (w jej definicji nie podano warunku). Ale wśród instrukcji, które występują w nawiasach klamrowych musi zaistnieć instrukcja warunkowa postaci:
if (warunek) break
gdyż jej brak uniemożliwi wyjście z pętli i uzyskanie jakichkolwiek wyników. Ponadto instrukcje w nawiasach klamrowych powinny zmieniać warunek, tak by mógł on być prawdziwy. Nieumiejętne używanie pętli repeat{…} jest dobrym sposobem na zablokowanie sobie komputera. Każe ona bowiem powtarzać instrukcje zawarte wewnątrz niej bez końca, o ile nie zostanie w niej umieszczona instrukcja warunkowa z poleceniem break. Uruchomienie instrukcji:
> repeat cat("Hello World!\n") |
wymagać będzie porzerwania wykonywania programu, bo R nie przestanie wyliczać ile razy ma powtórzyć wykonanie napisu. Należy kliknąć na “Różne” (Misc) i kliknąć na “przerwij bieżące obliczenia” (“stop current computation”) lub nacisnąć klawisz Esc. Prawidłowo zastosowana pętla repeat wygląda następująco:
> repeat { cat("Hello World!\n") + i=sample(5,1) + if (i==5) break } Hello World! Hello World! Hello World! Hello World! Hello World! Hello World! Hello World! |
Pętla repeat{…} może całkowicie zastąpić pętlę while(…){…} i vice versa. Przy takim zastępowaniu trzeba zmienić warunek na przeciwny, gdyż pętla while(…){…} przestaje działać gdy warunek w nawiasach okrągłych ma wartość FALSE a pętla repeat{…} przestaje działać gdy warunek w instrukcji warunkowej ma wartość TRUE. W zależności od problemu jedna z tych opcji daje bardziej przejrzysty kod.
Generalnie pętli repeat{…} wygodniej jest używać, gdy pewien zestaw instrukcji musi zostać co najmniej raz wykonany. Wtedy instrukcję warunkową z poleceniem break umieszcza się na końcu. Przykładem może być losowanie współrzędnych punktu należącego do koła jednostkowego. Funkcja, która losuje liczby z przedziału [-1,1], nosi w R nazwę runif() z opcjami min= i max=.
repeat{ x=runif(1,min=-1,max=1) y=runif(1,min=-1,max=1) if (x^2+y^2<1) break} cat(x," ",y,"\n") |
Po przeniesieniu do konsoli wygląda to następująco:
> repeat{ x=runif(1,min=-1,max=1) + y=runif(1,min=-1, max=1) + if (x^2+y^2<1) break} > cat(x," ",y,"\n") 0.8355987 -0.208568 |
Liczba pierwsza to liczba naturalna (całkowita dodatnia), która ma tylko dwa (różne) dzielniki dające resztę 0. Jest to 1 i ona sama. Najmniejsza liczba pierwszą jest 2, choć wielu matematyków włącza to także 1. Zadaniem jest utworzenie ciągu liczb pierwszych od 2 do z góry zadanej liczby N.
N=1000 x=2:N y=NULL repeat{ a=x[1] y=c(y,a) x=x[x %% a != 0] if (length(x)==0) break} y |
Po przeniesieniu do konsoli uzyskamy następujący obraz:
> N=1000 > x=2:N > y=NULL > repeat{ a=x[1] + y=c(y,a) + x=x[x %% a != 0] + if (length(x)==0) break} > y [1] 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 [22] 79 83 89 97 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 [43] 191 193 197 199 211 223 227 229 233 239 241 251 257 263 269 271 277 281 283 293 307 [64] 311 313 317 331 337 347 349 353 359 367 373 379 383 389 397 401 409 419 421 431 433 [85] 439 443 449 457 461 463 467 479 487 491 499 503 509 521 523 541 547 557 563 569 571 [106] 577 587 593 599 601 607 613 617 619 631 641 643 647 653 659 661 673 677 683 691 701 [127] 709 719 727 733 739 743 751 757 761 769 773 787 797 809 811 821 823 827 829 839 853 [148] 857 859 863 877 881 883 887 907 911 919 929 937 941 947 953 967 971 977 983 991 997 |