Einführung in R: Logische Werte

Boolesche Variablen können die beiden Werte TRUE und FALSE annehmen. Sie entstehen zum Beispiel bei Vergleichsoperationen und können durch zahlreiche logische Operationen miteinander verknüpft werden. Insbesondere um Fallunterscheidungen zu formulieren und den Ablauf eines Programmes zu steuern, werden sie eingesetzt.

Einordnung des Artikels

Einführung

Im letzten Abschnitt wurde mit den Vergleichsoperatoren eine Klasse von Funktionen vorgestellt, die einen logischen Wert (oder Wahrheitswert), also TRUE oder FALSE, annehmen. In diesem Abschnitt werden nun Variablen definiert, die logische Werte annehmen können, man bezeichnet sie meist als Boolesche Variable.

Um ein typisches Beispiel zu nennen: Es soll eine elektrische Schaltung simuliert werden, in der Schalter und Glühbirnen vorkommen; relevant sein soll nur, ob eine ausgewählte Glübirne brennt oder nicht — ihre Helligkeit sei irrelevant. Sowohl für die Schalterstellungen als auch für den Zustand der Glühbirnen gibt es dann nur zwei relevante Werte: Ein oder Aus, was man auch mit einem logischen Wert TRUE oder FALSE ausdrücken kann.

Logische Werte kommen natürlich nicht nur in solch technischen Anwendungen vor; beim Programmieren muss man immer wieder prüfen, ob eine Bedingung erfüllt ist oder nicht (und je nachdem einen anderen Befehl ausführen). Auch hier kommen logische Werte zum Einsatz. Und wenn die Prüfung dynamisch erfolgen muss — also etwa wenn x < y überprüft werden soll, aber x und y je nach Programmablauf andere Werte annehmen können -, setzt man Boolesche Variable ein.

In diesem Abschnitt wird das nötige Grundlagenwissen bereitgestellt, um mit logischen Werten und Booleschen Variablen in R zu arbeiten:

Boolesche Variable und logische Operationen

Initialisierung von Booleschen Variablen

Boolesche Variable können die beiden Werte TRUE und FALSE annehmen. Es gibt drei Möglichkeiten, wie eine Boolesche Variable initialisiert werden kann:

  1. Mit den Wahrheitswerten TRUE und FALSE (als Abkürzung kann auch T und F verwendet werden).
  2. Mit dem Ergebnis einer Vergleichsoperation.
  3. Auf den ersten Blick unverständlich: mit Zahlen. Diese Möglichkeit beruht darauf, dass Boolesche Variablen intern als Zahlen gespeichert werden; es steht 0 für FALSE und jede andere Zahl für TRUE.

Die drei Varianten werden nun im Deteil vorgeführt.

1. Die Wahrheitswerte TRUE und FALSE können direkt verwendet werden, um eine Boolesche Variable zu initialisieren:

b <- TRUE
b
# [1] TRUE

b <- FALSE
b
# [1] FALSE

b <- true       # FEHLER: nur TRUE und FALSE sind erlaubte Werte
b
# Fehler: Objekt 'true' nicht gefunden

# Abkürzung von TRUE und FALSE mit T und F:
b <- T
b
# [1] TRUE

b <- F
b
# [1] FALSE

Dabei ist zu beachten, dass die beiden Wahrheitswerte TRUE und FALSE groß geschrieben werden müssen (siehe Fehlermeldung in Zeile 9 bis 11). Es ist auch möglich, die Abkürzungen T und F zu verwenden (Zeile 14 und 18); man sollte aber beachten, dass die Quelltexte dadurch schwerer lesbar werden.

2. Im Abschnitt über Zahlen wurden die Vergleichsoperatoren besprochen; sie liefern als Ergebnis immer einen Wahrheitswert. Es ist daher auch möglich, eine Boolesche Variable mit dem Ergebnis einer Vergleichsoperation zu initialisieren. Im folgenden Skript geschieht dies, indem das Vorzeichen einer Variable x verwendet wird, um eine Boolesche Variable b zu setzen (Zeile 6):

n <- 17
m <- -1

x <- n*m

b <- (x > 0)

x           # -17
b           # FALSE

Mit Hilfe der logischen Operationen, die weiter unten besprochen werden, kann man auch deutlich komplexere Ausdrücke auf der rechten Seite der Zuweisung an die Boolesche Variable angeben (in Zeile 6).

3. Das folgende Skript zeigt die dritte Möglichkeit, wie Boolesche Variable initialisiert werden können: mit Hilfe von Zahlen.

b <- 0
b               # 0
mode(b)         # "numeric"

b <- as.logical(b)
is.logical(b)   # TRUE
b               # FALSE

b <- 1
b               # 1
mode(b)         # "numeric"

b <- as.logical(b)
is.logical(b)   # TRUE
b               # TRUE

b <- 1.5
b               # 1.5
mode(b)         # "numeric"

b <- as.logical(b)
is.logical(b)   # TRUE
b               # TRUE

Zur Erklärung:

1. Die Variable b wird zunächst immer als numerische Variable definiert (Zeile 1, 9 und 17). Man erkennt dies an mode(b) (siehe Zeile 3, 11 und 19).

2. Durch die Zuweisung (Zeile 5, 13, 21)

b <- as.logical(b)

wird b in ene logische Variable verwandelt. Dies wird in den Zeilen 6, 14 und 22 im Skript überprüft.

3. Die Variable b wird nach der Umwandlung (in eine logische Variable) ausgegeben (Zeile 7, 15 und 23):

Operatoren für Boolesche Variablen

Die Vergleichsoperatoren, die früher für Zahlen erläutert wurden, können auch für Boolesche Variable eingesetzt werden; man muss dabei beachten, dass TRUE und FALSE wie 1 und 0 behandelt werden:

# Vergleichsoperatoren

b1 <- TRUE
b2 <- FALSE

b1 == b2        # FALSE
b1 != b2        # TRUE

b1 < b2         # FALSE
b1 <= b2        # FALSE

b1 > b2         # TRUE
b1 >= b2        # TRUE

Viel wichtiger sind natürlich die logischen Operationen NOT, AND, OR, XOR (NICHT, UND, ODER, ENTWEDER ODER); für AND und OR gibt es zwei Versionen, deren Unterschied unten erklärt wird:

# logische Operationen

!b1             # NOT

b1 & b2         # AND
b1 && b2        # AND (short-circuit)

b1 | b2         # OR
b1 || b2        # OR (short-circuit)

xor(b1, b2)     # XOR

Der Operator && (logisches UND) besitzt folgende Eigenschaft:

Ist in

c <- a && b

a == FALSE , so ist auch c == FALSE , egal welchen Wert b besitzt. Daher wird im Fall von a == FALSE der Ausdruck

a && b

nicht vollständig ausgewertet, sondern es wird sofort c <- FALSE gesetzt.

Man nennt dieses Verfahren short-circuit evaluation.

Es wird auch beim logischen Oder || angewendet:

c <- a || b

Für a == TRUE muss c == TRUE sein (egal welchen Wert b hat) — auch hier wird sofort c <- TRUE gesetzt.

Dagegen wird bei den Operatoren & und | der komplette Ausdruck ausgewertet. Man kann dies testen, indem man einen Wahrheitswert mit einer Variable verknüpft, der noch keinen Wert zuordnet wurde — dazu wird eine Variable aus dem workspace gelöscht:

rm(b)               # Löschen der Variable b
b                   # Fehler: Objekt 'b' nicht gefunden

TRUE && b           # Fehler: Objekt 'b' nicht gefunden
FALSE && b          # FALSE (b wird nicht ausgewertet)

TRUE & b            # Fehler: Objekt 'b' nicht gefunden
FALSE & b           # Fehler: Objekt 'b' nicht gefunden

TRUE || b           # TRUE (b wird nicht ausgewertet)
FALSE || b          # Fehler: Objekt 'b' nicht gefunden

TRUE | b            # Fehler: Objekt 'b' nicht gefunden
FALSE | b           # Fehler: Objekt 'b' nicht gefunden

Ein weiterer wichtiger Unterschied zwischen den Operatoren & und && beziehungsweise | und || wird im Zusammenhang mit Vektoren erklärt. (Um den Unterschied schon anzudeuten: Bei den Operatoren & und | können die Eingabewerte auch Vektoren sein, die Ausgabe wid dann komponentenweise erzeugt; mit && und || können zwar auch Vektoren verknüpft werden, aber hier wird nur die jeweils erste Komponente weiterverarbeitet.)

Verwendung Boolescher Variabler

Im Folgenden werden zwei Beispiele gezeigt, die einen Hinweis darauf geben sollen, wie Wahrheitswerte eingesetzt werden; vollständig ausgeführt werden können die Beispiele noch nicht, da dazu mehr Wissen nötig ist, wie man Funktionen definiert beziehungsweise wie man mit Vektoren arbeitet.

Formulieren von Fallunterscheidungen

In der Mathematik werden häufig Fallunterscheidungen formuliert; diese lassen sich einfach mit Hilfe Boolescher Variabler vorbereiten, wie das folgende Beispiel zeigt:

Die folgenden Booleschen Variablen case1, ... , case5 beschreiben genau diese Fälle (es gibt natürlich zahllose Varianten, wie man dies erledigen kann):

rm(x)

x <- -10
isNegative <- (x < 0)

case1 <- (x < - 100)
case2 <- !case1 && isNegative
case3 <- (x == 0)
case5 <- (x > 100)
case4 <- !case5 && (x > 0)

# Test

case1           # FALSE
case2           # TRUE
case3           # FALSE
case4           # FALSE
case5           # FALSE

Das Beispiel ist wohl kaum überzeugend, da es noch sehr statisch ist. Damit ist gemeint, dass man sich zuerst den x-Wert vorgeben muss, anschließend die Fälle als Boolesche Variable definiert und dann erst feststellen kann, welcher Fall für das gegebene x vorliegt. Wünschenswert wäre es, dies Booleschen Variablen dynamisch einzusetzen, also zu einem beliebig vorgegeben x-Wert den zugehörigen Fall in Form der Booleschen Variable geliefert zu bekommen. Wie sich das realisieren lässt, wird gezeigt, wenn selbstdefinierte Funktionen besprochen werden. Zunächst sollte dieses Beispiel nur zeigen:

Der letzte Punkt erinnert daran, wie wichtig es ist, die Quelltexte möglichst leicht lesbar zu schreiben. Gerade die Kombinationen as mehreren logischen Operationen ist für den Menschen schwer lesbar und man kann die Terme falsch interpretieren. Achten Sie deshalb darauf:

Aufgabe: Trockentest

Versuchen Sie nachzuvollziehen, wie in obigem Skript die Booleschen Variablen case1, ... , case5 gesetzt werden.

Überprüfen Sie insbesondere, ob für x = -100 und x = 100 die richtige Boolesche Variable auf TRUE gesetzt wird.

Ausblick auf Anwendungen mit Vektoren

Die folgende Abbildung zeigt einen Vektor mit 15 Komponenten: in der ersten Zeile sind die Indizes dargestellt (von 1 bis 15), in der zweiten Zeile die Werte der Komponenten. Der Vektor wurde als eine Folge von Zufallszahlen erzeugt.

Abbildung 1: Folge von 15 Zufallszahlen, oben die Indizes, unten die zugehörigen Werte.Abbildung 1: Folge von 15 Zufallszahlen, oben die Indizes, unten die zugehörigen Werte.

Bei vielen Anwendungen, in denen Vektoren ausgewertet werden, müssen Zahlen gefiltert werden und man stellt etwa folgende Fragen:

Wenn Vektoren genauer untersucht werden, wird auch gezeigt, wie leicht man diese Fragen mit Hilfe von Vergleichsoperatoren und logischen Werten beantworten kann.

Zusammenfassung

Logische Operatoren

Die folgende Tabelle zeigt die in R verfügbaren logischen Operatoren:

Operator Beschreibung
! Verneinung (NICHT, NOT)
& Logisches UND (AND); bei Vektoren: komponentenweiser Vergleich
&& Logisches UND mit short-circuit evaluation (AND)
| Logisches ODER (OR); bei Vektoren: komponentenweiser Vergleich
|| Logisches ODER mit short-circuit evaluation (OR)
xor(a, b) ENTWEDER ODER (exklusiv ODER, XOR)
?Logic Dokumentation: Weitere Informationen im package base unter Logic

Vergleichsoperatoren

Da logische Werte als Zahlen interpretiert werden können (FALSE entspricht 0, TRUE entspricht 1), können die Vergleichsoperatoren zwischen Zahlen auch auf logische Werte angewendet werden; das Ergebnis ist immer ein logischer Wert.

Operation Beschreibung
a == b Test auf Gleichheit von a und b
a != b Test auf Ungleichheit von a und b
a > b Test, ob a größer ist als b
a < b Test, ob a kleiner ist als b
a >= b Test, ob a größer oder gleich b
a <= b Test, ob a kleiner oder gleich b
?Comparison Dokumentation: Weitere Informationen im package base unter Comparison