Formel - flutter-tutorial-de/dart-basics-tutorial GitHub Wiki

Table of Contents

Einleitung

Die meisten Programme müssen Daten manipulieren, d. h. aus vorhandenen Daten neue generieren. Dies geschieht vor allem mit "Rechenoperationen". Damit befasst sich dieses Kapitel.

Die Informatiker sprechen von einem Ausdruck (englisch: expression), was landläufig unter Formel verstanden wird, einer Verknüpfung von Operationen.

Es gibt einstellige Operationen, zweistellige Operationen und in Dart eine 3-stelligen Operation.

Einstellige Operationen

Bei einstelligen Operationen wird der Operator (das "Rechenzeichen") entweder davor oder danach notiert. Der bekannteste vorangestellte einstellige Operator ist das Minusvorzeichen, beispielsweise bei -2, was mathematisch gesehen den punktsymetrischen Spiegelpunkt auf dem Zahlenstrahl mit Symetriezentrum 0 liefert.

Zweistellige Operationen

  • Eine zweistellig Operation hat die Form: operand operator operand
  • Der Operator ist ein "Rechenzeichen", also + - / * usw.
  • Ein Operand ist eine Zahl, eine Variable, ein Funktionsaufruf oder eine evt. geklammerte Operation
Beispiel: 3 + (5.3 / 9)*faktor - quadrat(44.3)

Operatoren ("Rechenzeichen") haben Rangfolgen ("Präzedenzen"): Liegen 2 kombinierte Operationen vor, wird zuerst die mit höherer Präzedenz ausgeführt. Dies ist auch als "Punkt vor Strich"-Regel bekannt.

Ist eine Operation geklammert, wird zuerst der Inhalt der Klammer berechnet.

Beispiel: 1 + 3*(4 + 3)

  • '*' hat höhere Präzedenz als '+'
  • Also wird zuerst die Operation 3*(4 + 3) berechnet.
  • (4 + 3) ist geklammert, wird also zuerst berechnet. Ergibt 7.
  • Danach wird 3*7 berechnet, ergibt 21.
  • Schließlich bleibt noch 1 + 21, das Ergebnis steht damit fest.

Zahldarstellungen

Für unsere Beispiele brauchen wir noch Hexadezimalzahlen, daher folgende Erläuterung:

Dart kennt verschiedene Notationen für Zahlen:

  • Dezimalzahl: 123456
  • Hexadezimalzahl: 0x12ab oder 0xFF3 Syntax: 0x gefolgt von Hexadezimalziffern (0, 1 ... 9, 'a', 'b', ... 'f'), in Groß oder Kleinschreibung.
  • wissenschaftliche Schreibweise für Gleitpunktzahlen: 1.3E+3 (bedeutet 1.3 mal 10 hoch +3, also 1300).
Hinweis: Es existiert keine Schreibweise für Binärzahlen oder Oktalzahlen.

Numerische Ausdrücke

Die meisten Operationen sind für numerische Operanden definiert, deshalb beginnen wir mit ihnen.

Zweistellige numerische Operatoren

  • '+': Addition: Operanden haben den Typ int oder double.
  • '-': Subtraktion: Operanden haben den Typ int oder double.
  • '/': Division mit Ergebnis double. Operanden haben den Typ int oder double.
  • '~/: Division mit Ergebnis int: es wird abgerundet. Beispiel: 7 / 4 ergibt 1.75. Dagegen erbringt 7 ~/ 4 den Wert 1. Operanden haben den Typ int.
  • '%': modulo Operation, das ist der Divisionsrest. 7 % 3 ist der Divisionsrest von 7 / 3, also 1. Operanden haben den Typ int.
Die folgenden Bit-Operationen sind nur für Spezialisten. Bit-Operationen sind nur für Operanden vom Typ int.
  • Bit-Operation: Es wird die Operation für jedes Bit von Operand1 mit dem entsprechenden Bit von Operand2 durchgeführt, vom ersten bis zum 64.ten Bit (in 64-Bit-Umgebungen).
  • '|' bit-Or, die Bits von Operand1 werden mit den Bits von Operand2 verodert: sind beide Bits 0 ist das Ergebnis 0, sonst 1. (0x101 | 0x10) ergibt 0x111.
  • '&': bit-And, die Bits von Operand1 werden mit den Bits von Operand2 ver-AND-et: sind beide Bits 1, ist das Ergebnis 1, sonst 0 (0x1234 & 0xFF) ergibt 0x34.
  • '^': bit-Xor, die Bits von Operand1 werden mit den Bits von Operand2 ver-XOR-t: sind beide Bits gleich, ist das Ergebnis 0, sonst 1 (0xffff ^ 0xff00) ergibt 0x00ff.
  • '>>' Rechtsshift: Operand2 ist eine Ganzzahl. Operand1 wird um diese Anzahl nach rechts verschoben. (0x1400 >> 4) ergibt 0x140.
  • << Linksshift: Operand2 ist eine Ganzzahl. Operand1 wird um diese Anzahl nach links verschoben. (0x1400 << 4) ergibt 0x14000.

Einstellige vorangestellte Operatoren

  • '-' Negation: aus -(3+1) wird -4. Mathematisch: Spiegeln am Nullpunkt des Zahlenstrahls.
  • '+' ändert den Ausdruck nicht. +(3+1) ist 4.
  • '++': Inkrement. Wird unten erklärt.
  • '--': Dekrement. Wird unten erklärt.
  • '~': Einserkomplement: Bit-Operation (also nur für Spezialisten). Alle Bits werden invertiert (0 wird zu 1 und 1 zu 0). ~0xff121 ergibt 0xfff00ede
    • Erklärung für die Hexziffer '1' (kommt bei 0xff121 an 3.ter und 5.ter Stelle vor):
    • 1 als 4-stellige Binärzahl geschrieben: 0001
    • Bits vertauschen (aus 1 wird 0 und umgekehrt): 1110
    • Wandlung in Hexadezimal: 1*8 + 1*4 + 1*2 + 0*1 = 14 = 0xe

Prefix-Inkrement und -Dekrement

Dieser Operator kann nur bei einer Variable als Operand eigesetzt werden. Die Variable wird bei '++' um 1 erhöht bzw. bei '--' um eins erniedrigt (also verändert) und dieses Ergebnis geht in den Ausdruck ein.

void main() {
  var x = 4;
  var y = ++x + 10;
  print("x: $x y: $y");
}
  • Berechnung von y: zuerst wird der Wert von x um eins erhöht, also x wird 5. Dann wird x + 10 berechnet. y wird also zu 15.
  • Dieses scheinbar komplizierte Konstrukt des Inkrements wurde erfunden, um Schleifen einfach zu gestalten.
void main() {
  var max = 10;
  print("Count-Down:");
  while(--max > 0){
    print("$max...");
  }
}
  • Durch das Inkrement/Dekrement wird eine eigene Fortschaltung eingespart, da das --max bereits im Vergleich vorkommt und den Wert ändert.

Einstellige nachgestellte Operatoren

Es gibt zwei einstellige nachgestellte Operatoren, '++' und '--'. Diese werden Postfix-Inkrement bzw. Postfix-Dekrement genannt. Wieder ist eine Variable für die Operatoren notwendig. Im Unterschied zu den Prefix-Operatoren findet die Veränderung der Variable erst nach der Berechnung des Ausdrucks statt.

void main() {
  var x = 4;
  var y = x++ + 10;
  print("x: $x y: $y");
}
  • Bei der Berechnung von y wird der Wert von x (also 4) mit 10 addiert, ergibt 14. Danach wird das Postfix-Inkrement angewendet, x wird um 1 erhöht.

Dreistellige Operation: bedingter Wert

Syntax: bedingung ? wahr-wert : falsch-wert

Es wird die Bedingung überprüft. Ist sie wahr, ist das Ergebnis der Wahrwert, sonst der Falschwert.

void main() {
   for (var zahl=1; zahl <= 4; zahl++){
     print(zahl % 2 == 1 ? 'ungerade: $zahl' : 'gerade: $zahl');
  }
}
  • Die Schleife erzeugt die Zahlen 1 bis 4.
  • Für jede Zahl wird mittels zahl % 2 == 1 getestet, ob die Zahl ungerade ist. Ist das Ergebnis wahr, ist das Ergebnis des Ausdrucks der Wert zwischen '?' und ':', also 'ungerade: $zahl' gedruckt, sonst der Wert nach dem ':', also 'gerade: $zahl'.

Boolsche Operatoren (Bedingungen)

Die zweite wichtige Gruppe von Operationen haben Wahrheitswerte (Datentyp bool) als Ergebnis. Sie kommen beispielsweise in Bedingungen vor.

Der Datentyp bool

Für Anfänger ist dieser Datentyp ungewöhnlich, daher etwas Erklärung dazu:

Die Bezeichnung bool kommt von dem britischen Mathematiker, Logiker und Philosophen Georg Bool.

Der Datentyp 'bool' kann drei Werte annehmen:

  • null: das wird meistens als "undefiniert" interpretiert, das lassen wir vorläufig weg, Erklärung folgt später.
  • true
  • false
Mit diesen Werten können sogenannte logische Operationen vorgenommen werden:

In der Logik gibt es unter anderem folgende Operationen (ich verwende hier die englischen Namen):

  • A '''AND''' B: Umgangsprachlich "sowohl als auch": A AND B ergibt true, wenn A und B gleichzeitig true sind, sonst false.
  • A '''OR''' B: Umgangsprachlich "oder": A OR B ergibt false, wenn A und B gleichzeitig false sind, sonst true.
  • NOT A: Das wird logische Invertierung genannt. Wenn A true ist, ist das Ergebnis false, ist A false, ist das Ergebnis true.
Beispiel:
  • Ich habe Zahl x und ein Intervall von 0 bis 10.
  • Die Zahl liegt im Intervall, wenn x >= 0 AND x <= 10.
  • Ich prüfe die erste Bedingung: x >= 0 und dann die zweite Bedingung x <= 10. Nur wenn beide Bedingungen wahr sind, liegt die Zahl im Intervall.

Vergleichsoperatoren

  • '==': Prüfung auf Gleichheit. Sind Operand1 und Operand2 gleich, ist das Ergebnis true, sonst false. Die Operanden können jeden Datentyp haben, auch unterschiedliche: Wird eine Zahl mit einem String verglichen, ist das Ergebnis immer false.
  • '!=': Prüfung auf Ungleichheit. Sind Operand1 und Operand2 gleich, ist das Ergebnis false, sonst true. Die Operanden können jeden Datentyp haben, auch verschiedene: Wird eine Zahl mit einem String verglichen, ist das Ergebnis immer true.
  • '>': Größer als. Liefert true, wenn Operand1 echt größer als Operand2 ist. Die Operanden müssen numerisch sein.
  • '<': Kleiner als. Liefert true, wenn Operand1 echt kleiner als Operand2 ist. Die Operanden müssen numerisch sein.
  • '>=': Größer oder gleich. Liefert true, wenn Operand1 größer als Operand2 ist oder wenn beide gleich groß sind. Die Operanden müssen numerisch sein.
  • '<=': Kleiner oder gleich. Liefert true, wenn Operand1 kleiner als Operand2 ist oder wenn beide gleich sind. Die Operanden müssen numerisch sein.

Einstelliger logischer Operator

Es gibt einen einstelligen logischen Operator, er wird vor den Operanden gestellt:

  • '!': logische Negation: Ist der Operand true, wird das Ergebnis false, sonst true.

Zweistellige logische Operatoren

  • '&&': logisches AND: Sind beide Operanden true, ist das Ergebnis true, sonst false.
  • '||': logisches ODER: Sind beide Operanden false, ist das Ergebnis false, sonst true.

String-Operatoren

Der Datentyp String kennt zwei zweistellige Operatoren:

  • '+': Konkatenation: das Ergebnis ist die Zusammensetzung von Operand1 und Operand2.
  • '*': Operand1 hat den Typ String, Operand2 den Typ int. Das Ergebnis ist das mehrfache Aneinanderreihen von Operand1, genau so oft wie Operand2 angibt.
Beispiel:
void main() {
  final anrede = 'Herr';
  final name = 'Huber';
  print(anrede + ' ' + name);
  final bewertung = 5;
  final stern = '*';
  print('Bewertung: ' + stern * bewertung); 
}
  • print(anrede + ' ' + name);: Hier werden die drei Strings mittels '+' zusammengefügt und dann ausgegeben.
  • print('Bewertung: ' + stern * bewertung);: Da '*' höhere Präzedenz als '+' hat, wird zuerst die stern * bewertung berechnet, was '*****' ergibt. Diese Zwischenergebnis wird an 'Bewertung: ' angehängt und ausgegeben.

Zuweisungsoperatoren

Wie in allen C-ähnlichen Sprachen ist die Zuweisung an Variable eine zweistellige Operation. Das hat den Vorteil, dass mehrere Zuweisungen gleichzeitig erledigt werden können. Operand1 muss immer eine Variable sein.

void main() {
  String a, b;
  a = b = 'Hi';
  print("a: $a b: $b");
}
  • Zuerst wird b = 'Hi' ausgeführt, die Variable b bekommt also den Wert 'Hi'.
  • Das Ergebnis der Zuweisung ist der Wert der Variablen, also hier der Wert von b nämlich 'Hi'.
  • Dieser Wert wird der Variablen a zugewiesen.
Es gibt noch weitere Zuweisungsoperatoren, die verkürzte Schreibweisen sind:
  • '+=': der rechte Operand wird auf zum linken Operanden addiert: a += 5 ist die verkürzte Schreibweise für a = a + 5. Bei Stringvariablen wird Konkatenation (Aneinanderreihung) verwendet.
  • '-=': analog Subtraktion
  • '*=': analog Multiplikation. Bei Stringvariablen wird String-Multiplikation (Vervielfachung) verwendet.
  • '/=': analog Division
  • '~/=': analog ganzzahlige Division
  • '%=': analog Divisionsrest
Für Spezialisten:
  • '&=': analog Bit-AND
  • '|=': analog Bit-OR
  • '<<=': analog Linksshift
  • '>>=': analog Rechtsshift
Für bool-Variablen:
  • '&&=': analog AND-Verknüpfung
  • '||=': analog OR-Verknüpfung

Weiter geht es mit Kapitel Container.
⚠️ **GitHub.com Fallback** ⚠️