In onderstaande interactieve R sessie staat eerst een waarschuwing omdat de sqrt
functie alleen binnen de niet-negatieve reële getallen rekent.
> sqrt(-3)
[1] NaN
Warning message:
In sqrt(-3) : NaNs produced
NaN
is een acroniem voor "Not a Number" en wordt binnen R o.a. gebruikt om ontbrekende gegevens aan te geven.
Als je zonder zorgen vierkantwortels wilt uit kunnen rekenen moet je dus onderscheid kunnen maken tussen negatieve en niet-negatieve getallen. Je kunt hiervoor een voorwaardelijke instructie via if
gebruiken:
Onderstaand R script
x <- -3
if (x<0) {
cat("Er bestaat geen reële wortel van", x)
} else {
cat("sqrt(",x,") =", sqrt(x))
}
levert bij uitvoeren van de instructies de volgende tekst op
Er bestaat geen reële wortel van -3
\(\phantom{x}\)
De algemene vorm van een voorwaardelijke instructie (if instructie) staat hieronder. Lees de toelichting voor meer uitleg:
if (voorwaarde) {
ingesprongen instructies indien aan de voorwaarde voldaan is
} else {
ingesprongen instructies indien aan de voorwaarde niet voldaan is
}
Twee van bovenstaande regels zijn ingesprongen (beginnen in dit geval met vier spaties): één na de if
en één na de else
. Dit betekent dat precies dié regels onder controle van respectievelijk de if
en de else
staan. We hebben hier in cursief ingesprongen instructies... opgeschreven om aan te geven dat daar één of meer R instructies verspreid over meerdere regels kunnen staan. We noemen het gedeelte waarin de instructies staan die uitgevoerd worden als aan de voorwaarde voldaan is het then-gedeelte; het gedeelte waarin de instructies staan die uitgevoerd worden als niet aan de voorwaarde voldaan is heet het else-gedeelte. Welk gedeelte van de instructies uitgevoerd gaat worden hangt dus af van de waarde van de voorwaarde tijdens het uitvoeren van de code: als de voorwaarde de waarde TRUE
oplevert worden de instructies in het then-gedeelte uitgevoerd en vervolgt de uitvoer na de voorwaardelijke instructie; anders (d.w.z. bij de waarde FALSE
) worden de instructies in het else-gedeelte uitgevoerd. Het else-gedeelte mag ook ontbreken en dan gaat de uitvoer gewoon door waar de voorwaardelijke instructie eindigt
In onderstaand stroomdiagram wordt de mogelijke executie van de voorwaardelijke opdracht weergegeven.
![if-then-else instructie if-then-else instructie](/images/uploads/theory/5670/if_then_else_diagram.png)
In ons eerste voorbeeld hebben we een variabele een waarde gegeven die afhing van een conditie. Dit komt zo vaak voor dat er ook een inline voorwaardelijke instructie ifelse
mogelijk is in R. We hadden in het eerste voorbeeld ook de volgende R instructie kunnen gebruiken:
> wortel <- ifelse(x<0, "geen getal", sqrt(x))
We geven nog een voorbeeldsessie in R van de twee soorten van voorwaardelijke opdrachten, waarbij de berekening afhangt van het even of oneven zijn van een geheel getal. De voorwaardelijke instructie is over meerdere regels verspreid en de plustekens geven aan dat de instructie nog niet compleet is.
> x <- 5
> if (x %% 2 == 0) {
+ x <- x %/% 2
+ } else {
+ x <- 3*x + 1
+ }
> x
[1] 16
> x <- ifelse(x %% 2 == 0, x %/% 2, 3*x + 1)
> x
[1] 8
Tot slot geven we nog wat voorbeelden van geketende en geneste voorwaardelijke instructies. Bekijk ze goed, probeer ze te begrijpen en lees de toelichtingen bij de voorbeelden.
Als je het volgende R script uitvoert
getallen_NL <- c("een", "twee", "drie")
keuze <- sample(getallen_NL, 1)
cat(keuze, "\n")
if (keuze == "een") {
cat("one\n")
} else if (keuze == "twee") {
cat("two\n")
} else if (keuze == "drie") {
cat("three\n")
} else {
cat("???\n")
}
switch(keuze,
"een" = cat("one\n"),
"twee" = cat("two\n"),
"drie" = cat("three\n")
)
kan dit de volgende uitvoer opleveren (afhankelijk van de daadwerkelijk gemaakte keuze):
De functie sample
stelt ons in staat om een willekeurig element uit een vector van drie Nederlandstalige getalsnamen te selecteren.
Hierna is er een keten van voorwaardelijke opdrachten.
In deze voorwaardelijke vertakking wordt maar één keuze uiteindelijk gemaakt. In de laatste tak ontbreekt het else-gedeelte. Dit correspondeert in een niet-geketende voorwaardelijke opdracht met het volgende stroomdiagram:
![if-then diagram if-then diagram](/images/uploads/theory/5670/if_then_diagram.png)
Omdat de geneste condities wat onoverzichtelijk kunnen worden, zelfs als de else if
constructie wordt gebruikt, is er in R ook een switch
constructie om verschillende gevallen te onderscheiden.
Lees bij onderstaand voorbeeld de toelichting voor informatie over de opmaak van afgedrukte getallen.
Als je het volgende R script uitvoert
r <- runif(1) # een random getal tussen 0 en 1
io <- sprintf("r = %.2f\n", r) # geformatteerde tekst
cat(io)
if (0.25<r) {
if (r<0.75) {
io <- sprintf("%.2f is een getal tussen 0.25 en 0.75\n", r)
}
}
cat(io)
kan dit de volgende uitvoer opleveren:
r = 0.39
0.39 is een getal tussen 0.25 en 0.75
0.39 is een getal tussen 0.25 en 0.75
Met de runif(1)
functie genereren we een willekeurig floating-point getal tussen 0 en 1 volgende de uniforme verdeling. Door een if instructie binnen een if instructie aan te roepen, ook wel genest gebruik van voorwaardelijke opdrachten geheten, kunnen we nagaan of het getrokken getal in het segment \([0.25, 0.75]\) ligt en dan een uitspraak hierover af te drukken. Maar er zijn twee korte, meer begrijpelijke afkortingen mogelijk. Je kunt voorwaarden combineren met een logische operator. In dit voorbeeld gebruiken we de &&
operator om te testen of aan twee voorwaarden voldaan is.
In dit voorbeeld hebben we ook een voorbeeld van opgemaakte uitvoer geïntroduceerd:
maakt een string waarbij het meegegeven floating-point getal afgedrukt is met 2 cijfers achter de decimale punt.
Onderstaande tabel vat de meest gebruikte opmaakspecificaties samen.
\[\begin{array}{l|c|l}
\textit{type } & \textit{specificatie} & \textit{toelichting} \\ \hline
\text{integer} & \mathtt{\%}w\mathbf{d} & \text{Het gehele getal wordt in een veld van breedte }w\text{ geplaatst}\\[-2pt]
& & w \text{ mag weggelaten worden.}\\ \hline
\text{double} & \mathtt{\%}w.d\mathbf{f} & \text{Het floating-point getal wordt in een veld van breedte }w\\[-2pt]
& & \text{geplaatst (inclusief de decimale punt) met } d \text{ decimale cijfers}\\[-2pt]
& & w\text{ en }d\text{ mogen weggelaten worden.}\\ \hline
\text{double} & \mathtt{\%}w.d\mathbf{e} & \text{Het floating-point getal wordt in een veld van breedte }w\\[-2pt]
&\mathtt{\%}w.d\mathbf{E} & \text{ geplaatst} \text{(inclusief de decimale punt) met } d \text{ decimale cijfers in}\\[-2pt]
& & \text{wetenschappelijke notatie. }w\text{ en }d\text{ mogen weggelaten worden.}\\ \hline
\text{numeric} & \mathtt{\%}\mathbf{g} \text{ of } \mathtt{\%}\mathbf{g} & \text{compacte decimale notatie of wetenschappelijke notatie.}\\ \hline
\text{character} & \mathtt{\%}w\mathbf{s} & \text{De string wordt in een veld van breedte }w\text{ geplaatst.}
\end{array}\]
Behalve het newline escape karakter \n
zijn er nog meer escape karakters. Onderstaande tabel vat de meest gebruikte escape karakters samen.
\[\begin{array}{c|l}
\textit{escape karakter } & \textit{gebruik} \\ \hline
\backslash\text{b} & \text{1 karakter terugschuiven}\\ \hline
\backslash\text{n} & \text{nieuwe regel}\\ \hline
\backslash\text{t} & \text{tabstop}\\ \hline
\backslash\texttt{'} & \text{enkel aanhalingsteken}\\ \hline
\backslash\texttt{"} & \text{dubbel aanhalingsteken}\\ \hline
\backslash\backslash & \text{schuine streep }\backslash
\end{array}\]