| 5. Arithmetik und Variablen |
5.1 Variablen
In den letzten Kapiteln war schon mehrfach von Variablen die Rede. Nun wollen wir sie etwas genauer betrachten.
Sie kennen Variablen aus der Mathematik als Platzhalter für Zahlen. Man kann mit Variablen ausdrücken, daß eine Formel gilt - unabhängig welche Zahlen man für die darin enthaltenen Variablen einsetzt.
In allen gängigen Programmiersprachen erfüllen Variablen die gleiche Funktion: Sie können stellvertretend für Zahlen angegeben werden. Man kann einer Variablen einen Wert zuweisen. Überall, wo diese Variable dann im Programm vorkommt, wird sie dann so behandelt als stünde da direkt der Wert dieser Variablen.
[LET] <Variablenname>=<Ausdruck>
Mit dem LET-Befehl gibt man einer Variablen einen Wert. Hatte diese Variable zuvor bereits einen anderen Wert, so wird dieser überschrieben. Der LET-Befehl kann auch weggelassen werden.
A=5
weist also der Variablen A den Wert 5 zu.
Das folgende Beispiel berechnet mit Hilfe der Formel des Pythagoras die Länge der langen Seite (Hypotenuse) eines rechtwinkligen Dreiecks:
100 INPUT "LAENGE DER 1. KATHETE:"; A
110 INPUT "LAENGE DER 2. KATHETE:"; B
120 C = SQR( A*A + B*B )
130 PRINT "LAENGE DER HYPOTENUSE: "; C
Der Name einer Variable kann aus einem oder zwei Zeichen bestehen. Das erste Zeichen muß ein Buchstabe sein, das zweite Zeichen kann auch eine Ziffer sein. Zwar ist es erlaubt, längere Variablennamen zu verwenden, der Basic-Interpreter identifiziert allerdings nur die beiden ersten Buchstaben.
Hinter dem Namen der Variable kann noch ein Zeichen stehen, das den Variablentyp bestimmt. Wenn kein Zeichen angegeben wird, bedeutet das, daß es sich um eine numerische Variablen (Rechenvariablen) handelt. Das Prozentzeichen kennzeichnet Integervariablen, die nur eine ganzstellige Zahl enthalten können (eher selten in Verwendung). Das Dollarzeichen kennzeichnet Stringvariablen, die keinen Zahlenwert sondern eine Zeichenkette (Buchstaben, Ziffern und Sonderzeichen) enthalten.
Zulässige Variablennamen wären z.B.:
F
F8
FAKTOR
FA (tatsächlich die gleiche Variable wie FAKTOR)
I%
NA$
Nicht zulässig wäre z.B. die Variable "IF", da Namen von Variablen keine Basic-Schlüsselwörter enthalten dürfen.
Ferner gibt es drei festgelegte Variablen, die vom System selbst mit Werten versorgt werden. Die Variable ST gibt den Status bei Ein-/Ausgabeoperationen mit Peripheriegeräten wieder, TI ist die interne Uhr, die in 1/60 Sekunden hochzählt, und TI$ enthält die Uhrzeit ab dem Einschalten des Computers als Stringvariable im Format "HHMMSS". Die Variablen ST und TI können nur abgefragt, TI$ kann mit TI$="HHMMSS" auch gesetzt werden.
Ebenfalls als eine systeminterne Konstante ist die Zahl PI fest definiert. Ihr ist eine eigene Taste zugeordnet. Sie können PI wie eine numerische Variable in Berechnungen verwenden.
5.2 Rechnen mit Zahlen
Ein Computer wäre kein Computer, könnte er nicht rechnen. Bisher haben Sie in den Programmbeispielen fast nur die Grundrechenarten sehen können. Basic kann aber noch mehr:
Als Operatoren bezeichnet man die normalen mathematischen Rechenzeichen. Neben den bereits vorgestellten "+" (Addition), "-" (Subtraktion), "*" (Multiplikation) und "/" (Division) kennt Basic noch Klammern zur Festlegung der Auswertungsreihenfolge eines Ausdrucks und das "^" als Exponentzeichen.
2*(4+1) ergibt 10
3^2 ergibt 9
5/2 ergibt 2.5
Am Ergebnis des letzten Beispiels sehen Sie, daß Basic auch mit nichtganzen Zahlen umgehen kann. Entgegen der in Deutschland gebräuchlichen Notation wird in Basic jedoch statt dem Komma ein Punkt verwendet.
Die logischen Vergleichsoperationen, die Sie im Kapitel über die Verzweigung schon kennengelernt haben, können ebenfalls zum Rechnen verwendet werden. Das Prinzip ist, daß eine erfüllte Bedingung den Wert -1 zugewiesen bekommt, eine nicht erfüllte Bedingung den Wert Null.
(1<2) ergibt -1
(1=2) ergibt 0
Beim Auswerten solcher logischer Ausdrücke sollten Sie Klammern verwenden, um die Hierarchie der Rechenoperationen klarzustellen.
INT() rundet auf die nächste ganze Zahl ab.
INT( 5.32 ) ergibt 5
INT( -2.3 ) ergibt -3
ABS() bildet den Betrag.
ABS( 23 ) ergibt 23
ABS( -4 ) ergibt 4
SIN() errechnet den Sinus. Das Argument wird im Bogenmaß erwartet. Das gleiche gilt für den Cosinus COS() und den Tangens TAN().
SIN( 3.1415 / 2 ) ergibt 1
SGN() liefert 1 bei positivem Argument, -1 bei negativem Argument und 0, falls das Argument gleich Null ist.
SGN( 0.3 ) ergibt 1
SGN( -1423 ) ergibt -1
SQR() errechnet die Quadratwurzel.
SQR( 16 ) ergibt 4
LOG() bestimmt den natürlichen Logarithmus, EXP() die Exponentialfunktion (d.h. die Eulersche Zahl hoch dem Argument).
LOG( 1 ) ergibt 0
EXP( 1 ) ergibt 2.7172...
DEF FN<Name>(<Parameter>)=<Ausdruck>
FN<Name>(<Argument>)
Sie können nicht nur mit den vorgefertigten Basicfunktionen arbeiten. Wenn eine Formel in einem Programm mehrfach benötigt wird, kann es nützlich sein, sie als Funktion zu definieren. Im Gegensatz zu anderen Programmiersprachen ist die Funktionsdefinition in Basic sehr eingeschrängt, sie darf nämlich nur eine einfache Formel enthalten. Programmierer höherer Programmiersprachen kennen Funktionen hingegen als Unterprogramme mit Rückgabewert.
Als Beispiel sei hier eine Sinusfunktion aufgeführt, deren Argument statt im Bogenmaß in Grad angegeben werden kann:
DEF FNSG(X)=SIN(X/180*)
Die nach dem Definitionsnamen in Klammern angeführte Variable (X) ersetzt in der Formel den Wert, mit dem sie später, beim Aufruf der Funktion, "gefüttert" werden soll. Es handelt sich dabei um einen reinen Platzhalter. Bei Aufruf der Funktion mit FN wird der in der Klammer mitgegebene Wert an richtiger Stelle in die Formel eingesetzt. Nun können Sie die neue Funktion mit vorangestelltem "FN" genauso nutzen, wie jede vorgefertigte Basicfunktion auch:
FNSG(90) ergibt 1
FNSG(270) ergibt -1
Berechnet den Arkustangens. Das Ergebnis ist im Bogenmaß.
Arcussinus und Arcuscosinus sind nicht verfügbar und müssen errechnet bzw. als Funktion definiert werden:
DEF FNAS(X) = ATN(X/SQR(1-X^2))
DEF FNAC(X)=-ATN(X/SQR(1-X^2))+/2
RND(<Basiswert>)
RND() liefert Pseudozufallszahlen, die zwischen 0 und 1 liegen. "Pseudo" deshalb, weil die Zahlen nicht ganz zufällig sind:
Ist der Basiswert > 0 (der Wert selbst spielt dabei keine Rolle), werden Zufallszahlen berechnet, wobei jede Zufallszahl aus der vorherigen erzeugt wird. Da der Startwert beim Einschalten des Computers vorgegeben wird, liefert RND(1) bei jedem Start immer die gleiche Folge von Zufallszahlen.
Eine Basiszahl < 0 produziert keine eigentliche Zufallszahl, sondern einen neuen Startwert, der aus der negativen Basiszahl selbst berechnet wird. Mit jedem so erzeugten Startwert kann dann mit RND(1) eine andere, aber ebenfalls immer reproduzierbare Folge von Zufallszahlen erzeugt werden.
Die Basiszahl 0 erzeugt Zufallszahlen aus einem internen Zeitgeber. RND(0) ergibt also jedesmal eine andere Zahl. Allerdings ist die Zahlenfolge auch nicht wirklich zufällig. Daher sollte RND(0) oder RND(-TI) nur zum Setzen eines zufälligen Startwertes verwendet werden, die weiteren Zahlen werden dann besser mit RND(1) gewonnen.
Die FRE-Funktion ermittelt den aktuell freien Arbeitsspeicher des Rechners. Das Argument wird dabei nicht ausgewertet, normalerweise gibt man daher FRE(0) an. Die Funktion wird wohl am häufigsten im Direktmodus verwendet:
? FRE(0)
Dabei ist zu beachten, daß FRE eine Vorzeichenbehaftete 16-Bit-Zahl ausgibt. Liegt der freie Arbeitsspeicher demzufolge über 32767, liefert FRE(0) ein negatives Ergebnis! Das korrekte Ergebnis erhält man in diesem Fall durch Addition von 65536.
AND und OR sind logische Operatoren, die zwei Argumente miteinander verknüpfen. Abgesehen von ihrer Bedeutung in der Formulierung von Bedingungen für Verzweigungen läßt sich damit auch rechnen, allerdings nur im Wertebereich von Integerzahlen (-32768 bis +32767). Die Argumente werden bitweise verknüpft.
255 AND 3 ergibt 3
1 OR 2 ergibt 3
(255 OR 1)-(255 AND 1) ergibt 254, also ein EXCLUSIV-OR
Ein praktischer Nutzen eröffnet sich vor allem dann, wenn Speicherstellen des Systems bitweise manipuliert werden müssen.
NOT ist ein logischer Operator mit nur einem Argument. Er invertiert alle Bits des Arguments im Wertebereich von Integerzahlen (-32768 bis +32767). Durch die etwas undurchsichtige Vorzeichenbehaftung von Integerzahlen ist NOT das wahrscheinlich am seltensten benutzte Element von Basic V2 überhaupt.
(NOT 3) AND 255 ergibt 252
5.3 Strings
Strings sind Zeichenketten, d.h. eine Abfolge von Buchstaben, Zahlen oder Sonderzeichen. Es gibt spezielle Variablen, die anstelle von Zahlen Strings als Wert annehmen können. Diese werden als Stringvariablen bezeichnet und durch ein Dollarzeichen am Ende des Variablennamens kenntlich gemacht.
Mit Strings kan man natürlich nicht im herkömmlichen Sinne rechnen. Zumindest die Addition ist jedoch definiert. Sie hängt die "Summanden" einfach aneinander.
A$="DIES IST "
B$="EIN BEISPIEL"
C$=A$+B$
PRINT C$
Der PRINT-Befehl schreibt den Wert der Stringvariablen C$ auf den Bildschirm. Es erscheint
DIES IST EIN BEISPIEL
Verschiedene Funktionen ermöglichen sehr interessante Anwendungen von Strings:
LEN() ermittelt die Länge eines Strings
LEN( "HALLO" ) ergibt 5
| LEFT$(), RIGHT$(), MID$() | LEFT$( <String>, <Anzahl Zeichen> )
RIGHT$( <String>, <Anzahl Zeichen> )
MID$( <String>, <ab Zeichen Nr>, <Anzahl Zeichen> )
Mit diesen Funktionen können Sie Teile von Strings ermitteln. LEFT$ liefert die angegebene Anzahl Zeichen vom Anfang des Strings, RIGHT$ ebenso aber vom Ende des Strings und mit MID$ können Sie die angegebene Anzahl von Zeichen ab einer bestimmten Position im String ausschneiden
LEFT$( "DONAUDAMPFSCHIFF", 5 ) ergibt DONAU
RIGHT$( "DONAUDAMPFSCHIFF", 6 ) ergibt SCHIFF
MID$( "DONAUDAMPFSCHIFF", 6, 5 ) ergibt DAMPF
Jeder Buchstabe, jede Ziffer und jedes Sonderzeichen wird vom Computer intern als Zahl gespeichert. Welches Zeichen dabei welcher Zahl entspricht, ist in einem Code festgelegt. Etwa die Hälfte dieses Codes ist standardisiert und auf jedem Computer gleich. Dieser Code heißt "ASCII" (american standard code for information interchange).
Mit der ASC()-Funktion können Sie die Zahl ermitteln, die dem ersten Zeichen des angegebenen Strings zugeordnet ist.
ASC( "A" ) ergibt 65
Die umgekehrte Funktion zu ASC() stellt CHR$() dar. Die angegebene Zahl wird in das zugehörige Zeichen nach dem ASCII-Code umgewandelt.
CHR$( 65 ) ergibt "A"
So können Sie sehr einfach ein Programm schreiben, das eine ASCII-Codetabelle auf den Bildschirm schreibt:
100 FOR I=0 TO 252 STEP 4
110 FOR J=0 TO 3
120 PRINT I+J; ":"; CHR$( I+J ); " ";
130 NEXT J
140 PRINT
150 NEXT I
Zu beachten ist dabei, daß die Codes 0 bis 31 und 128 bis 159 keine druckbaren Zeichen, sondern Anweisungen zur Bildschirmsteuerung enthalten, die mit dem PRINT ausgeführt werden. Code 147 bewirkt z.B. das Löschen des Bildschirms.
VAL wandelt einen Zahlenstring in eine Zahl, STR$ tut genau das Gegenteil. Stößt VAL bei der Umwandlung des Strings auf ein Zeichen, das nicht zu einem Zahlenstring paßt, bricht die Wandlung ab.
Auch hier wird die Wirkungsweise wohl am ehesten durch einige Beispiele klar:
VAL( "12" ) ergibt die Zahl 12
VAL( "35.6" ) ergibt die Zahl 35,6
VAL( "23.07.1998" ) ergibt 23,07 (eine Zahl kann nur ein Komma enthalten)
VAL( "7A12" ) ergibt die Zahl 7 (der Rest läßt sich nicht als Zahl lesen)
STR$( 14.5 ) ergibt den String "14.5"
STR$( 64 ) ergibt den String "64"
5.4 Felder
Oft ist es notwendig, viele gleichartige Informationen in Variablen abzulegen. Der einfachste Weg, dies zu tun ist die Verwendung von Feldvariablen. Einem Variablennamen kann dabei eine vorher festzulegende Anzahl verschiedener Werte zugewiesen werden. Dem Variablennamen wird dabei in runden Klammern ein Index mitgegeben, der die verschiedenen möglichen Werte mit Nummern versieht.
DIM <Variablenname>(<Anzahl Feldelemente>[,Elemente 2. Dimension][...])
Die Anzahl möglicher verschiedener Werte in einer Feldvariable muß festgelegt werden, bevor die zugehörige Feldvariable erstmals benutzt wird. Dazu dient der DIM-Befehl.
100 DIM U(12)
110 FOR I=1 TO 12
120 PRINT "UMSATZ IM "; I; ". MONAT DES JAHRES:";
130 INPUT U(I)
140 NEXT I
150 FOR I=1 TO 12
160 PRINT I,
170 FOR J=1 TO U(I)
180 PRINT "#";
190 NEXT J
200 PRINT
210 NEXT I
Das Beispielprogramm definiert in Zeile 100 eine Feldvariable mit 12 Elementen. In den Zeilen 110 bis 140 werden diese dann vom Anwender des Programms mit Werten gefüllt. Der Rest des Programms gibt die eingegebenen Werte dann als Balkendiagramm wieder aus.
Felder können auch mehrdimensional angelegt werden. DIM M(10,10,10) dimensioniert beispielsweise eine dreidimensionale Matrix. Die Anzahl der Dimensionen läßt sich praktisch unbegrenzt erweitern, allerdings stößt der Speicherbedarf solcher Felder rasch an Grenzen.
5.5 Programminterne Daten
Oftmals werden in einem Programm Daten benötigt, die fest hinterlegt sein sollen, d.h. nicht jedes mal von Neuem abgefragt werden sollen. Basic bietet dafür einen einzigartigen Mechanismus: Beliebige Daten können, durch Komma getrennt, in sogenannten DATA-Zeilen abgelegt werden. Diese können an jeder beliebigen Stelle im Programm stehen. Stößt der Basicinterpreter bei der Programmabarbeitung auf eine DATA-Zeile, so wird diese vorerst ignoriert.
Der Zugriff auf DATA-Zeilen erfolgt durch den READ-Befehl. Dieser ist in der Verwendung stark an den INPUT-Befehl angelehnt. Die Informationen werden jedoch nicht von der Tastatur eingelesen, sondern von vorn nach hinten aus den im Programm vorhandenen DATA-Zeilen. Sollen Daten mehrfach gelesen werden, so können Sie per RESTORE-Befehl veranlassen, daß READ wieder mit dem Anfang der DATA-Zeilen beginnt. Ein selektiver Zugriff auf die in Data-Zeilen abgelegten Werte ist nicht möglich.
Nochmals im Detail:
DATA <Konstante>[,<Konstante>][...]
Hinter dem Data-Befehl folgen eine oder mehrere Konstanten, wobei es sich dabei um Zahlen oder Zeichenketten handeln darf. Die Trennung erfolgt durch Kommas, Zeichenketten sollten in Anführungszeichen eingeschlossen werden.
READ <Variablenname>[,<Variablenname>][...]
Die nächste Konstante oder (bei mehreren angegebenen Variablennamen) die nächsten Konstanten aus den DATA-Zeilen werden gelesen und als Wert(e) der/den angegebenen Variablen zugewiesen.
Ein Beispiel dürfte die Verwendung von Read und Data etwas anschaulicher machen. Es handelt sich dabei um eine abgewandelte Fassung des Balkendiagramm-Generators aus der Erklärung des DIM-Befehls:
100 DIM U(12)
110 FOR I=1 TO 12
130 READ U(I)
140 NEXT I
150 FOR I=1 TO 12
160 PRINT I,
170 FOR J=1 TO U(I)
180 PRINT "#";
190 NEXT J
200 PRINT
210 NEXT I
1000 DATA 5, 8, 9, 13, 12, 18, 20, 17, 11, 8, 1, 0
Als nächste per READ zu bearbeitende DATA-Zeile wird wieder die erste DATA-Zeile des Programms festgelegt.
|