Die Addition »… + …« in C♯
Einführendes Beispiel
In C♯ kann auch eine Summe in der gewohnten Schreibweise als Ausdruck verwendet werden. Die Addition wird mit dem Pluszeichen »+« geschrieben.
Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( 1 + 1 ); }}global::System.Console.Out
2
Syntax
Wir erweitern das Syntaxdiagramm für Ausdrücke um den Additionsoperator »+«.
- Neue, erweiterte Syntax
Ausdruck
.----------.
---.----------->| Literal |---------------------------.---->
| '----------' |
| .-. .----------. |
'--->( - )-->| Ausdruck |---------------------------'
| '-' '----------' |
| .-. .----------. |
'--->( + )-->| Ausdruck |---------------------------'
| '-' '----------' |
| .-. .----------. .-. |
'--->( ( )-->| Ausdruck |-->( ) )-------------------'
| '-' '----------' '-' |
| .----------. .-. .----------. |
'----------->| Ausdruck |-->( / )-->| Ausdruck |----'
| '----------' '-' '----------' |
| .----------. .-. .----------. |
'----------->| Ausdruck |-->( + )-->| Ausdruck |----'
'----------' '-' '----------'
Die Addition wird mit dem Pluszeichen »+« geschrieben. Sind A und a zwei Ausdrücke, so ist A +a wieder ein Ausdruck, die Summe von A und a. Dabei wird A auch Augend und a Addend genannt. (Diese vereinfachte Syntax bringt die Priorität und Assoziativität der Addition nicht richtig zum Ausdruck. Diese beiden werden daher weiter unten separat erklärt.)
Typanforderungen
Der Augend und der Addend kann jeden der bisher vorgestellten Typen haben.
Typ
Ist der Typ des einen Operanden »string«, so wird der Wert des anderen Operand in diesen Typ gewandelt, und das Ergebnis der Addition hat den Typ »string«. Andernfalls gilt: Ist der Typ des einen Operanden »double«, so wird der Wert des anderen Operand nach »double« gewandelt, und der Typ des gesamten Ausdrucks hat den Typ »double«. Sonst hat der gesamte Ausdruck den Typ »int«.
Typregeln für den Fall, daß ein Operand den Typ »string« hat
- string + … → string
… + string → string
Typregeln für den Fall, daß kein Operand den Typ »string« hat
- double + … → double
… + double → double
int + int → int
Wert
Bei der Auswertung einer Addition werden beide Operanden ausgewertet. Der Wert eines Additionsausdrucks mit einer Zeichenkette ist die Verkettung (Hintereinanderschreibung) der Zeichenketten (Zeichenfolgen) der beiden Operanden (Beispiele dazu folgen weiter unten). Der Wert eines Additionsausdrucks mit numerischen Operanden ist die Summe dieser Operanden.
Numerische Operanden
Wir betrachten zunächst numerische Operandenausdrücke. Bei diesen erfolgt die Typangleichung so wie bei der Division, nur daß es hier weniger Überraschungen mit Nachkommastellen gibt, weil die Addition zweier ganzzahliger Werte auch in der Mathematik keine Nachkommastellen ergibt.
Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( 1 + 1 ); }}global::System.Console.Out
2
Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( 1 + 1.0 ); }}global::System.Console.Out
2
Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( 1.0 + 1 ); }}global::System.Console.Out
2
Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( 1.0 + 1.0 ); }}global::System.Console.Out
2
Zeichenfolgenaddition
Der Operator »+« ist wie der zuvor vorgestellte Operation »/« polymorph und hat sogar noch eine zusätzliche „Überladung“ (d.h.: Bedeutung) für den Typ »string«. Falls beide Operanden Zeichenfolgen sind, so bedeutet dieser Operator die Schreibung der rechten Zeichenfolgen hinter die linke (also eine Hintereinanderschreibung / Verkettung in der gegebenen Reihenfolge).
Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( "1." + "2.a" ); }}global::System.Console.Out
1.2.a
Zeichenfolgenaddition mit Zahlen
Bei Ausdrücken der Signatur int +string, string +int, double +string oder string +double wird, wie schon oben festgehalten, der jeweils andere Operandenwert auch nach string gewandelt (also in eine Darstellung als Zeichenfolge umgewandelt) und anschließend eine Verkettung der beiden Zeichenfolgen vorgenommen.
Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( 2 + "3a" ); }}global::System.Console.Out
23a
Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( "2" + 3 ); }}global::System.Console.Out
23
Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( 2 + "x" ); }}global::System.Console.Out
2x
Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( 3.0 + "x" ); }}global::System.Console.Out
3x
Zeichenfolgendarstellung
Die Addition des leeren Textes zu einer Zahl wird manchmal verwendet, um diese als Zeichenfolge darzustellen (in eine Zeichenfolge umzuwandeln). Später werden im Kurs auch noch Fälle gezeigt werden, in denen solch eine Umwandlung nützlich ist.
Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( "" + 2 ); }}global::System.Console.Out
2
Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( 2 + "" ); }}global::System.Console.Out
2
An den obenstehenden Programmbeispielen kann man aber noch nicht erkennen, daß wirklich etwas umgewandelt wurde. Das folgende Programm zeigt aber deutlich, daß »( 2 + "" )« ein string ist, weil bei der folgenden Addition von »3« eine Verkettung und keine arithmetische Summierung vorgenommen wird.
Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( ( 2 + "" )+ 3 ); }}transcript
23
Zum Vergleich mit dem vorigen Programm zeigt das folgende Programm die arithmetische Summierung.
Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( ( 2 + 0 )+ 3 ); }}global::System.Console.Out
5
Gelegentlich wird die Wandlung in eine Zeichenfolge mit »+ ""« als „unverständlich“ kritisiert. Es wird behauptet, daß ein Leser eines Programms an »+ ""« die Absicht des Programmierers, etwas in eine Zeichenfolge zu wandeln, nicht erkennen könne. Diese Kritik ist allerdings nicht berechtigt. Falls ein C♯ -Programmierer die Bedeutung von »+ ""« nicht kennt, dann liegt dies daran, daß er seine Ausbildung noch nicht beendet hat – aber man kann schlecht verlangen, Programme für Leser schreiben, welche die Programmiersprache noch gar nicht kennen. Falls ein C♯ -Programmierer die Bedeutung von »+ ""« aber kennt, dann ist es ihm auch klar, daß damit eine Umwandlung in eine Zeichenfolge beabsichtigt ist, denn warum sollte jemand »+ ""« sonst verwenden?
Polymorphie
An diesem Operator kann man die Bedeutung des Wortes Polymorphie besonders gut erklären, weil hier offensichtlich zwei ganz verschiedene Operationen in Abhängigkeit vom Typ der Operanden ausgeführt werden: die arithmetische Summierung und die Zeichenfolgenverkettung.
- Arithmetische Summierung
123 + 456
- Zeichenfolgenverkettung
"a" + "b"
Ohne Polymorphie würde man für die Zeichenfolgenverkettung einen anderen Operator verwenden (wie beispielsweise »&« oder ».«).
Die Polymorphie ist in diesem Falle umstritten, da man es in Frage stellen kann, ob man das Verketten von Zeichenketten als eine Art von „Addition“ ansehen darf. Falls dem nicht so wäre, dann wäre es falsch oder schlechter Stil, das Additionszeichen »+« dafür mitzuverwenden. Jedoch könnte man dies dann nur den Gestaltern der Programmiersprache vorwerfen, nicht aber ihren Benutzern (also den Programmierern). Deswegen sollte sich der Leser durch diese Bedenken nicht davon abhalten lassen, die Verkettung mit dem Pluszeichen »+« jederzeit zu verwenden, wenn sie ihm als nützlich erscheint.
Die Kritiker sehen in dem mathematischen Symbol »+« ein Zeichen, das für eine kommutative Operation steht, eine Operation also, bei der die Reihenfolge der Operanden auch vertauscht werden kann, ohne das Ergebnis (die Summe) zu ändern. Sie sagen, daß das Summenzeichen für die Zeichenfolgenverkettung nicht verwendet werden sollte, weil diese nicht kommutativ ist. Dabei übersehen sie aber, daß man das Symbol »+« auch in der Mathematik manchmal für nicht-kommutative Operationen (in Monoiden) verwendet. Außerdem ist die Polymorphie mit ihrer „metaphorischen Verwendung“ von Verben ein wichtige Eckpfeiler der objektorientierten Programmierung (wie später im Kurs behandelt werden wird), und daher paßt es zu einer objektorientierten Programmiersprache, diese auch bei Operatoren zu verwenden. Schließlich gibt es in der Praxis keine Probleme mit dieser Überladung des +-Operators.
Linksassoziativität
Ohne Klammerung wird bei einer Addition der Form »… + … + …« zuerst die am weitesten links stehende Summe auswertet. (Dabei stehen die Ellipsen »…« für Literale, Klammerausdrücke oder Quotienten.)
In dem folgenden Programmbeispiel wird daher zuerst eine numerische Summe berechnet und erst danach eine Zeichenfolgenverbindung vorgenommen.
In der folgenden Darstellung der bei der Auswertung eines Ausdrucks erfolgenden Operationen, gehört zu jeder Operation ein nach rechts weisender Pfeil. Der von der Operation ausgewertete Teilausdruck ist durch einen waagerechten Strich über ihm gekennzeichnet.
Operationen bei der Auswertung von »1 + 2 + "4"«:
- Operation arithmetische Summierung von »1« und »2«, Ergebnis »3«.
_____
1 + 2 + "4" →
3 + "4"- Operation Wandlung von »3« in die Zeichenfolge »"3"« und Verkettung von »"3"« und »"4"«, Ergebnis »34«.
_______
3 + "4" →
"34"Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( 1 + 2 + "4" ); }}global::System.Console.Out
34
Operationen bei der Auswertung von »"1" + 2 + 4«
- Operation Wandlung von »2« in die Zeichenfolge »"2"« und Verkettung von »"1"« und »"2"«, Ergebnis: »"12"«.
_______
"1" + 2 + 4 →
"12" + 4- Operation Wandlung von »4« in die Zeichenfolge »"4"« und Verkettung von »"12"« und »"4"«, Ergebnis: »"124"«.
________
"12" + 4 →
"124"Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( "1" + 2 + 4 ); }}global::System.Console.Out
124
Das folgende Programmbeispiel zeigt eine Kombination aller drei Typen »int«, »double« und »string«.
Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( 1 + 2.0 + "a" ); }}global::System.Console.Out
3a
Das folgende Programmbeispiel zeigt, daß die Addition der leeren Zeichenfolge »""« einen Text nicht verändert, so wie die Addition von »0« eine Zahl nicht verändert.
Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( ">" + "" + "<" ); }}global::System.Console.Out
><
Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( 1 + 0 + 1 ); }}global::System.Console.Out
2
Priorität
Die Priorität der Addition ist kleiner als die der Division. Das heißt, daß ein Ausdruck, der ein Literal oder ein Klammerausdruck ist und direkt zwischen einem »+« und einem »/« steht, zu dem »/« gezählt wird.
Operationen bei der Auswertung von »2 + 4.0/2«.
- Operation Wandlung von »2« in »2.0« und Division von »4.0« durch »2.0«, Ergebnis: »2.0«.
_____
2 + 4.0/2 →
2 + 2.0- Operation Wandlung von »2« in »2.0« und Addition von »2.0« und »2.0«, Ergebnis: »4.0«.
________
2 + 2.0 →
4.0Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( 2 + 4.0/2 ); }}global::System.Console.Out
4
Um eine spezielle gewünschte Zusammenfassung zu erreichen, können Ausdruckklammern verwendet werden.
Operationen bei der Auswertung von »( 2 + 4.0 )/2«.
- Operation Wandlung von »2« in »2.0« und Addition von »2.0« und »4.0«, Ergebnis: »6.0«.
___________
( 2 + 4.0 )/2 →
6.0 /2- Operation Wandlung von »2« in »2.0« und Division von »6.« durch »2.0«, Ergebnis: »3.0«.
_____
6.0/2 →
3.0Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( ( 2 + 4.0 )/ 2 ); }}global::System.Console.Out
3
Vorzeichen haben eine höhere Priorität als die Addition:
Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( -3 + 9 ); }}global::System.Console.Out
6
Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( -( 3 + 9 ) ); }}global::System.Console.Out
-12
In der folgenden Tabelle haben die Operatoren eine höhere Priorität, die weiter oben stehen.
- Priorität der bisher behandelten Operatoren
() Eingeklammerter Ausdruck
+ - Unaere vorangestellte Operatoren
/ Division
+ Addition
Formatierung
Leeraum kann frei verwendet werden, um Ausdrücke übersichtlich zu schreiben.
- Beispiele
2+4.0/2 2 + 4.0/2 2 + 4.0 / 2
- Beispiele
(2+4.0)/2 ( 2 + 4.0 )/ 2 ( 2 + 4.0 ) / 2
- Beispiel eines Ausdrucks, der über 3 Zeilen geht
( 2 + 4.0 )
/
2
»decimal« und »string«
Die Verkettung einer Zeichenfolge mit einem decimal-Wert ist möglich.
Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( "3" + 3m ); }}global::System.Console.Out
33
Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( 3m + "3" ); }}global::System.Console.Out
33
decimal-Additionen
Bei Additionen mit decimal-Ausdrücken sind dieselben Kombinationen von Typen erlaubt wie zuvor bei Divisionen beschrieben. Bei nicht zu großen Werten ist die Skalierung der Summe das Maximum der Skalierungen der Operanden.
Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( 1.000m + 1.00m ); }}global::System.Console.Out
2.000
Bei großen Summen können hintere Stellen mit Werten unter 1 ungenau sein.
Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( 12345678901234567890m + 0.12345678901234567890m ); }}global::System.Console.Out
12345678901234567890.123456789
Numerische Überläufe
Summen können so groß werden, daß sie mit ihrem Typ nicht mehr darstellbar sind. In dem folgenden Beispiel sind die einzelnen Summanden als int-Werte darstellbar. Die Summe hat nach den Typregeln ebenfalls den Typ »int«, ist aber nicht mehr als int-Wert darstellbar, da sie dafür zu groß ist.
Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( 2147483647 + 2147483647 ); }}global::System.Console.Out
Program.cs(4,7): error CS0220: The operation overflows at compile time in checked mode
- global::System.Console.Out (übersetzt)
Program.cs(4,7): Fehler CS0220: Ueberlauf bei Uebersetzung in pruefendem Modus
Eine Web-Suche nach »Compiler Error« gefolgt von der Fehlerkennung, also beispielsweise nach »Compiler Error CS0220«, liefert weitere Informationen zu jener Kennung.
Die Abstraktion des unsichtbaren Implementation (black box ) *
Der Operator »+« wird in der Regel nur dadurch beschrieben, welches Ergebnis er liefert. Die Technik, wie der Operator »+« es erreicht, das richtige Ergebnis zu „finden“ wird verborgen. Dadurch wird der Verwender dieses Operators davon entlastet, sich über die Details der Umsetzung Gedanken machen zu müssen.
Man kann dies mit einer Maschine wie beispielsweise einem Fahrstuhl vergleichen: Der Bediener muß nur wissen, welche Wirkung die einzelnen Knöpfe haben (er muß also nur die Oberfläche zur Bedienung kennen), aber nicht, wie die Technik das im einzelnen realisiert. Das Innere der Maschine ist für den Benutzer nicht sichtbar (abstrahiert).
Die Umsetzung von Funktionen wird Implementation (hier wäre dies also die „Implementation der Addition“) genannt. Die Implementation wird in der Programmierung oft verborgen.
Diese Abstraktion der „unsichtbaren Implementation“ (black box ) ist eine der wichtigsten Techniken, die in der Programmierung zur Beherrschung der Komplexität großer Programm eingesetzt wird.
Übungsfragen
? Ausdrücke
Welcher der folgenden Ausdrücke hat denselben Wert wie »1 / 2+3«?
- »1/( 2+3 )« Anton
- »( 1/2 )+ 3« Berta
? Ausdrücke
Welche Werte haben die folgenden Ausdrücke jeweils?
- A »1/2.0 + 1/2«
- B »1/( 1.0 + 1 )«
- C »1 +( 9 + "C" )«
- D »1 + 5 + "A"«
/ Bezeichnung eines Ausdrucks
Würden Sie den Ausdruck »2 + 4/2« als eine Summe oder als einen Quotienten bezeichnen? Begründen Sie ihre Wahl!
? Verständnis von Fachbegriffen
Welchen Wert hat der Ausdruck »12/4+2«?
Angenommen die Addition hätte keine niedrigere Priorität als die Division, sondern eine höhere. Welchen Wert hätte dann der Ausdruck »12/4+2«?
Übungsaufgaben
/ Terme
Die in der Mathematik vorkommenden Schreibweisen für Werte werden Terme genannt. In C♯ verwendet man keine Terme. Die Ausdrücke von C♯ haben aber Ähnlichkeit mit Termen. Viele Terme lassen sich auch als Ausdruck schreiben und umgekehrt.
Schreiben Sie möglichst kurze Ausdrücke für die folgenden Terme, ohne vorher irgendwelche Teile der Terme im Kopf auszurechnen. Die Werte der Ausdrücke sollten den mathematischen Werten der vorgegebenen Terme möglichst nahe kommen, also den Werten, die man in der Grundschule als Werte der Terme ansehen würde.
- Term (Ein Halb plus drei Viertel, erwartete Ausgabe zirka »1.25«)
1 3
--- + ---
2 4- Term (Drei plus Vier im Zähler und Fünf plus Sechs im Nenner, erwartete Ausgabe zirka »0.6363636363636364«)
3 + 4
---------
5 + 6
Falls beim Lösen der zweiten Übungsaufgabe die Lösung der ersten Übungsaufgabe noch aufbewahrt werden soll, so ist es am besten, die Lösung der ersten Übungsaufgabe in eine extra Textdatei zu kopieren, damit die Lösung der zweiten Übungsaufgabe übersichtlich bleibt. Es spricht aber auch nichts dagegen, wenn beim Lösen der zweiten Übungsaufgabe die Lösung der ersten Übungsaufgabe wieder verloren geht.
/ Beschriftung einer Ausgabe
Berechnen Sie mit C♯ die Summe 2+3 (diese soll nicht im Kopf ausgerechnet werden) und geben Sie das Ergebnis dann mit dem Text »2 + 3 = « (acht Zeichen) davor und dem Text ».« (ein Zeichen) dahinter aus.