Logische Bedingungen

<< Click to Display Table of Contents >>

Navigation:  Datenmodifikation > Berechnung >

Logische Bedingungen

Das Keyword IF erlaubt die Berechnung von Variablen sowie deren Werte und ausgewählter Eigenschaften unter der Kontrolle logischer Bedingungen.

Das folgende Kapitel behandelt

die erlaubten Vergleichsoperatoren zur Formulierung logischer Bedingungen und

den Mengenoperator IN zur einfachen Anwendung für Mehrfachnennungsvariablen,

arithmethische Formeln innerhalb von IF-Statements,

die einfache Testung auf fehlende Werte und Variablentypen,

die Optionen COPY und LOAD,

bedingte Umcodierung von Werten bzw. Wertebereichen,

Alphanumerische und Alpha-Vergleiche, damit zusammenhängend die Einstellung IGNORECASEINCOMPARE sowie

FIF als Variante von IF, die gegebene Filtersetzungen beachtet, mit der Einstellung IFASFIF.

Weiterhin erlaubt IFBLOCK die Formulierung mehrerer, verschachtelter IF-Bedingungen, mit WHILEBLOCK DO werden entsprechende Schleifen abgearbeitet.


If... Then... Else

IF-Formulierungen erlauben in Kombination mit THEN und ELSE die Neuberechnung von Variablen unter der Kontrolle von logischen Bedingungen.

Syntax:

IF <bedingung> THEN <anweisung> [ ELSE <anweisung> ] ;

<anweisung> ist ein beliebiges COMPUTE-Statement unter Weglassen des Keywords COMPUTE.

Erlaubte Vergleichsoperatoren:

EQ

Equal, ist gleich

NE

Not Equal, ist ungleich

GT

Greater Then, größer als

GE

Greater Equal, größer/gleich

LT

Lower Then, kleiner als

LE

Lower Equal, kleiner/gleich

IN

Einschluss von Wertemengen/-bereichen

Logische Verknüpfungen sind möglich mit:

AND

Und

OR

Oder

NOT

Nicht

Assoziationen müssen explizit durch Klammerung angegeben werden; ungeklammerte Reihungen von OR und AND werden von links nach rechts abgearbeitet. Die verbreitete abkürzende Schreibweise (z.B. "a EQ 1 OR 2" anstelle von "a EQ 1 OR a EQ 2" etc. ist nicht erlaubt. Hierfür gibt es die IN-Formulierung. Stringkonstanten sind erlaubt.

Mengenoperator IN

Vergleiche mit IN erlauben auf einfache Weise einen Test auf die Existenz von Werten in 
Mehrfachnennungsvariablen. Die Teste sehen z.B. so aus:

IF 4 IN famvar_01 THEN ...;

Auf der rechten Seite muss eine Variable oder eine numerische Konstante stehen. Auf der linken Seite des Mengentests darf ein Wert, eine Werteliste, eine atomare oder eine Mehrfachnennungsvariable stehen. Ein Test auf Zahlenbereiche wird z.B. folgendermaßen geschrieben:

IF [ 1 : 13 ] IN Frage11 then ...;

Zahlenbereiche dürfen mit Einzelwerten gemischt werden (wie auch im RECODE). z.B.:

IF [ 1 3 55 : 60 -0.1 : 0.1 ] IN ...;

Auf der rechten Seite solcher Vergleiche mit dem IN-Operator dürfen auch Variablenlisten stehen, die in runde Klammern eingeschlossen werden müssen, z.B.:

IF [ 1 2 3 ] IN ( var1 var7 to var10 ) THEN ....;

Arithmetische Formeln

Arithmetische Formeln in IF-Bedingungen sind möglich.

Syntax:

IF <arithmetische Berechnungsvorschrift> 
[ LT GT LE GE EQ NE ] 
<arithmetische Berechnungsvorschrift> THEN ...

Zum Beispiel:

IF < a + 1 > EQ c THEN ...

An die Stelle eines Wertes oder einer Variablen kann eine in spitze Klammern gesetzte arithmetische Berechnungsvorschrift treten.

Die spitzen Klammern sind erforderlich, damit der Compiler schnell erkennen kann, um welchen Typ von Vergleich es sich handelt.

Zusätzlich zu den oben beschriebenen Vergleichen mit LT, GT, LE, GE, EQ und NE) kann man arithmetische Berechnungsvorschriften auch anstelle einzelner Konstanten bei Vergleichen mittels IN verwenden. Es ist also auch möglich, z.B.

IF < a + 1 > IN b THEN ....

zu schreiben. Der erweiterte Gebrauch von IN mit Wertemengen (der auf einen Vergleich der Schnittmenge mit der leeren Menge hinausläuft) erlaubt diese Verwendung nicht.

Verboten ist also bspw.:

IF [ < a + 1 >  2 3 4 ] IN b THEN ...

THEN und ELSE

Für die Formulierung des THEN oder ELSE-Teils gelten die Beschreibungen der arithmetischen Formulierung wie bei COMPUTE.

Beispiel:

IF a GE 3 THEN

x = c * ( 4 - d )

ELSE

x = e / ( d + c );

Der ELSE-Teil der Anweisung kann auch weggelassen werden, zum Beispiel:

IF a EQ 3 THEN d = 5;

Test auf fehlende Werte

Man kann mit IN alle Variablentypen durchgehend auf fehlende Werte testen.

Hierfür gibt es eine vom System zur Verfügung gestellte Testvariable: SYSMISS.

Der Test auf "enthält keine gültigen Werte" lautet z.B.:

IF SYSMISS IN <variable> THEN ...;

Der Test auf "enthält mindestens einen gültigen Wert" lautet entsprechend:

IF NOT ( SYSMISS IN <variable> ) THEN ...;

Wenn auf der linken Seite eine Mehrfachnennungsvariable steht, gilt der Test als wahr, wenn die Schnittmenge der linken und rechten Menge nicht leer ist.

Test auf Variablentyp

Man kann im Bedingungsteil von IF auch den Typ einer Variablen testen.

Dies ist i.d.R. nur in Macros nötig, die u.U. einen formalen Parameter bekommen, der irgendeinen Variablentyp enthält.

Der Test hat folgende Syntax:

IF <varname> IS <vartype> THEN ... [ ELSE ... ] ;

Als "<vartype>" darf

VARIABLE, SINGLEQ

FAMILYVAR, MULTIQ

GROUPVAR, DICHOQ

OPEN

stehen. (Begriffe in einer Zeile sind bedeutungsgleich.)

Copy und Load

Im IF-Statement gibt es (analog zum COMPUTE COPY-Statement) die COPY-Option, mittels dessen ganze Variablenlisten kopiert werden können.

Zum Beispiel:

IF a EQ x THEN

COPY v1 TO v10 = x1 TO x10

ELSE

COPY v1 TO v10 = y1 TO y10;

Dasselbe gilt auch für die LOAD-Option (vgl. COMPUTE LOAD), z.B.:

IF a EQ x THEN

LOAD fam = group1

ELSE

LOAD fam = group2;

Bedingte Umcodierung (Filterungen)

Auch in IF-Statements können ganze Variablenlisten arithmetisch geändert werden. Wenn man z.B. Fragenfilterungen explizit setzen will, kann man Einzelvariablen oder Variablenlisten auf den definierten MISSING-Code setzen. Zum Beispiel:

IF Frage13 EQ "Nichtraucher" THEN Frage14 TO Frage23a = -1;

Anmerkung: An dieser Stelle wäre das FILTER-Statement natürlich eleganter.

Alphanumerische Vergleiche

Wie man im obenstehenden Beispiel sieht, kann sowohl auf numerische als auch alphanumerische Konstanten getestet werden. Alphanumerische Konstanten werden in Anführungszeichen oder Hochkommata eingeschlossen ( ",’ ). Werden alphanumerische Konstanten mit Variablen verglichen, wird das VALUELABEL des aktuellen Werts zum Vergleich herangezogen. Bei ALPHA-Variablen ist dies der aktuell eingelesene String, bei anderen Variablen ist dies das Label. Zum Beispiel:

IF Partei EQ "SPD" THEN ...;

Sobald auf einer Seite des Vergleichs eine Stringkonstante auftaucht, wird der Vergleich als Textvergleich durchgeführt. Größer und Kleiner (GT oder LT) z.B. werden dann als lexikalische Vergleiche anhand des ASCII-Codes durchgeführt: »AA« ist kleiner als »aa«, usw.

Es kann hier auch zu Runtime-Errors kommen: wenn man eine Variable auf einen String testet, diese Variable aber einen numerischen Wert hat, für den kein Label definiert ist, dann ist der Test nicht entscheidbar. GESStabs löst dann einen Runtime-Error aus.

Achtung: Es gibt eine syntaktische Problematik: Da man auch Variablen in Anführungszeichen einschließen muss, wenn man besondere Variablennamen benutzt (z.B. Variablennamen, die Blanks enthalten), ist syntaktisch nicht eindeutig zu entscheiden, was mit einem Token in Anführungszeichen in einer IF-Bedingung gemeint ist. GESStabs interpretiert Strings in Anführungszeichen oder Hochkommata als Variablennamen, wenn es eine Variable mit dem entsprechenden Namen gibt, sonst als Textkonstante. Variablen, die man in IF-Bedingungen verwenden will, sollte man daher mit einfachen Token benennen, die man nicht in Anführungszeichen setzen muss. Für die Tabellenausgaben kann man die erläuternden Texte als VARTITLE deklarieren.

Alpha-Vergleiche

Syntax:

IF <alpha> IN <alphavar> THEN ....

<alpha> ::= Textkonstante oder ALPHA-Variable
<alphavar> ::= ALPHA-Variable

In dieser einfachen Variante wird getestet, ob ein beliebiger Text in einem ALPHA-Wert vorkommt. Sei aaa eine Variable vom Typ ALPHA, dann kann mit IN getestet werden, ob eine Textkonstante z.B. "abc" in dieser Variable enthalten ist:

IF "abc" IN aaa THEN...

Man kann auch prüfen, ob der Text einer ALPHA-Variablen im Text einer anderen Variable enthalten ist:

Seien aaa und bbb beides Variablen vom Typ ALPHA, dann kann man mit

IF bbb IN aaa THEN...

darauf testen, ob der ALPHA-Inhalt von bbb Bestandteil von aaa ist.

Es gibt auch einen Wildcard-Vergleich:

Enthält die Textkonstante auf der linken Seite des Vergleichs "*" oder "?", dann wird ein Wildcard-Vergleich durchgeführt, wobei jedes "?" für einen beliebigen Buchstaben steht und * für mehrere.

Beispiel:

IF "a?c.txt" IN aaa THEN...

würde dementsprechend TRUE liefern für:

a1c.txt
a2c.txt
abc.txt
usw.

Diese Form des Vergleichs gibt es nur bei Textkonstanten; wenn auf der linken Seite des Vergleichsoperators IN eine Variable steht, dann wird KEIN Mustervergleich durchgeführt, auch wenn deren Text ein "*" oder "?" enthält.

IgnoreCaseInCompare

Bezugnehmend auf Alphanumerische Vergleiche und Alpha-Vergleiche.

Syntax:

IGNORECASEINCOMPARE = [ YES | NO ];

Default: NO

Alle Textvergleiche (EQ, NE, LE, GE, LT, GT und IN) unter Beteiligung von Stringkonstanten und/oder ALPHA-Variablen werden im Standardfall case-sensitive durchgeführt, d.h. "abc" ist unterschiedlich zu "ABC" oder "Abc" usw.

Setzt man den Schalter IGNORECASEINCOMPARE auf YES, werden die Vergleiche durchgeführt, ohne dass zwischen Klein- und Großbuchstaben unterschieden wird. Hierfür werden alle Labeltexte vor dem Vergleich in Kleinbuchstaben gewandelt. Grundsätzlich werden auch Zeichen außerhalb des ASCII-Codessets, wie z.B. ä und Ä oder é und É, richtig zugeordnet. Da dies aber vom lokalen Setting des Betriebssystems abhängig sein kann, ist im Zweifel Kontrolle angebracht; deutsche Umlaute sind okS, ebenso griechische, hebräische oder osteuropäische Schriftzeichen.

Anmerkung: Unabhängig von dieser Einstellung werden die Inhalte von ALPHA-Variablen beim Einlesen immer entsprechend der aktuellen Einstellung zu ALPHACASESENSITIVE behandelt. Im Default also "case-insensitive".

Fif... Then... Else

Parallel zum oben erläuterten IF-Statement gibt es das FIF-Statement, das mit einem kleinen Unterschied völlig parallel funktioniert: das FIF-Statement beachtet mit SETFILTER gesetzte Filter. Steht ein FIF-Statement zwischen SETFILTER ... ENDFILTER, wird dann, wenn der Filter nicht offen ist (d.h. die Filterbedingung nicht wahr ist), weder der THEN- noch der ELSE-Part ausgeführt.

IfasFif

Syntax:

IFASFIF = [ YES | NO ];

Wird dieser Schalter auf YES gesetzt, dann werden alle IF-Statement und alle COMPUTE-Statements nur dann ausgeführt, wenn die SETFILTER-Hierarchie insgesamt "true" ergibt, Mit anderen Worten: jedes IF wird als FIF interpretiert, und jedes COMPUTE als FCOMPUTE.


IfBlock, ElseBlock, EndBlock

In einem Block aus IFBLOCK (, ELSEBLOCK) und ENDBLOCK können beliebig viele Statements stehen. Außerdem können Blöcke geschachtelt werden.

Syntax:

IFBLOCK <bedingung> THEN
//hier können mehrere computes/ifs etc stehen
ELSEBLOCK
//hier können mehrere computes/ifs etc stehen
ENDBLOCK;

Die Komponente ELSEBLOCK ist optional.

Von dieser Logik betroffen sind: alle COMPUTEs, alle Formen von IF (IF ... THEN, IF ... PRINT, IF ... LOAD) alle RECODEs, COUNT und MEAN.

Alle übrigen Statements ignorieren die IFBLOCK-Anweisungen.

Mehrere IFBLOCKs können ineinander geschachtelt werden. Die maximale Tiefe, d.h. Anzahl aktiver IFBLOCKs, beträgt 512.

Beispiel (Block mit Tiefe 2):

IFBLOCK A EQ 1 THEN

   IFBLOCK B EQ 1 THEN

     COMPUTE E = 1;

     COMPUTE Z = sqrt( ln( 10 ) );

   ELSEBLOCK

     COMPUTE E = 2;

   ENDBLOCK;  

ELSEBLOCK

   IFBLOCK B EQ 1 THEN

     COMPUTE E = 3;

   ELSEBLOCK

     COMPUTE E = 4;

   ENDBLOCK;  

ENDBLOCK;


WhileBlock Do

Syntax:

WHILEBLOCK <bedingung> DO
// hier können mehrere computes/ifs etc stehen
// oder auch z.b. IFBLOCK-konstrukte
ENDBLOCK;

 

WHILEBLOCK DO ist die GESStabs-Version einer Schleife. Alles, was zwischen DO … ENDBLOCK steht, wird solange durchlaufen, bis Die gesetzte Bedingung nicht mehr gilt.

Beispiel einer Schleife mit einem Zähler v:

COMPUTE v = 10; 

COMPUTE Summe = 0;

WHILEBLOCK v GT 0 DO

    COMPUTE t = v MOD 2;

    IF t EQ 1 THEN Summe = Summe + v;

    COMPUTE v = v - 1;

ENDBLOCK;

Die Schleife beginnt mit v=10 und wird dann bis v=1 durchlaufen. Nur wenn die Testgröße t =1 ist, wird v auf Summe addiert. Damit werden alle ungeraden Zahlen zwischen 1 und 10 addiert.

Nach mehr als 10.000.00 Durchläufen der Schleife wird die Software mit einer Exception beendet.