Ta strona wykorzystuje ciasteczka ("cookies") w celu zapewnienia maksymalnej wygody w korzystaniu z naszego serwisu. Czy wyrażasz na to zgodę?

Czytaj więcej
< All Topics
Print

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

 

Spis treści