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
|