Gleichheitsaussagen in C♯
Einführendes Beispiel
Es wurde schon gezeigt, wie Aussagen mit Aufrufen geschrieben werden können: »System.Char.IsDigit( "A", 0 )«.
Es gibt auch einige Operatoren zum Schreiben von Aussagen. Mit ihnen können beispielsweise Aussagen über die Gleichheit zweier Werte geschrieben werden.
Der Operator »==« ist ein binärer Infixoperator, der es erlaubt, zu schreiben, daß die Werte beider Operanden gleich sind.
Haben beide Operanden denselben Wert, so ist der Wert der Gleichheitsaussage »true«, sonst »false«.
Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine( 1 + 2 );
global::System.Console.WriteLine( 1 == 2 );
global::System.Console.WriteLine( 1 == 1 ); }}Protokoll
3
False
True
Vereinfachte Syntax
- Produktionsregel
Ausdruck
.----------. .--. .----------.
--->| Ausdruck |--->( == )-->| Ausdruck |--->
'----------' '--' '----------'
Die beiden Operanden einer Gleichheitsaussage werden manchmal auch als Komparanden bezeichnet.
Priorität
Die folgende Tabelle gibt die Assoziativität und Priorität der bisher behandelten Operatoren wieder.
- Priorität und Assoziativität der bisher behandelten Operatoren
x.y f(x) primaere Schreibweisen
+ - Unaere vorangestellte Operatoren
L * / Multiplikation, Division
L + - Addition, Subtraktion
L == Gleichheitsaussage
R = Zuweisung
Die Priorität des Gleichheitsoperators erlaubt es beispielsweise die Aussage »2 + 3 == 4« oder die Zuweisung »b = 2 == 4« ohne Klammern zu schreiben.
Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine( 2 + 3 == 4 );
bool b; b = 2 == 4;
global::System.Console.WriteLine( b ); }}Protokoll
False
False
Typen
Typanforderungen (vereinfacht)
Die Typen der beiden Operanden müssen entweder gleich sein oder es muß sich um eine Kombination von »int« und »double« oder »decimal« handeln. Im zweiten Falle wird der int -Wert vor dem Vergleich nach »double« beziehungsweise »decimal« gewandelt.
- Mögliche Gleichheitsaussagen (symbolische Schreibweise)
int == int
string == string
bool == booldouble == double
int == double (als double == double)
double == int (als double == double)decimal == decimal
int == decimal (als decimal == decimal)
decimal == int (als decimal == decimal)
Typangleichung
Der Wert von »7« und der Wert von »7.0« sind unterschiedlich, da diese Ausdrücke zwei verschiedene Datentypen haben. Bei der Aussage »7==7.0« wird der Wert »7« aber zunächst nach »double« gewandelt. Es wird dann praktisch »7.0==7.0« ausgewertet. Daher ergibt »7==7.0« true, obwohl die Werte eigentlich unterschiedlich sind, da sie sich in den Datentypen unterscheiden. Dies führt aber in der Praxis nicht zu Problemen, sondern ist meist eher nützlich. Falls einem dies mißfällt, kann man ja darauf verzichten, Gleichheitsaussagen mit Operanden unterschiedlicher Typen zu formulieren oder sich eine eigene Methode für Vergleiche definieren.
Typ des Ausdrucks
Der Typ eines mit diesem Operator gebildeten Ausdrucks zur Gleichheitsaussage ist immer »bool«.
Semantik
Semantik (allgemein)
Bei der Auswertung dieses Operators werden zunächst immer beide Operanden ausgewertet.
Semantik (Wert) bei gleichen Typen
Haben beide Ausdrücke denselben Typ, dann gilt: haben beide Ausdrücke denselben Wert, so ist der Wert der Gleichheitsaussage »true«, sonst »false«.
Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine( 1 == 2 );
global::System.Console.WriteLine( 0.0 == 0.00 );
global::System.Console.WriteLine( "2.0" == "1.9999999999999999" );
global::System.Console.WriteLine( true == false ); }}Protokoll
False
True
False
False
Semantik (Wert) bei int==double-Vergleichen
Sind die Werte beider Ausdrücke nach der Wandlung in den Typ »double« gleich, so ist der Wert der Gleichheitsaussage »true«, sonst »false«.
Semantik (Wert) bei int==decimal-Vergleichen
Sind die Werte beider Ausdrücke nach der Wandlung in den Typ »decimal« gleich, so ist der Wert der Gleichheitsaussage »true«, sonst »false«.
Semantik (Wert) bei double==double-Vergleichen
Bei double==double-Vergleichen kann das Ergebnis des Vergleichs anders sein als man es erwartet, wenn man die Rechnungen im Kopf durchführt.
Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine( 0.1 + 0.2 == 0.3 );
global::System.Console.WriteLine( 1.1 * 1.1 == 1.21 );
global::System.Console.WriteLine( 1E30 == 1E30 + 1 ); }}Protokoll
False
False
True
True
Da das Ergebnis von double==double-Vergleichen zu sehr von kleinsten Abweichungen in den hintersten Stellen abhängen kann, sind Aussagen zur Gleichheit von double-Werten in der Regel nicht sinnvoll.
Jedoch können Vergleiche von double-Werten doch sinnvoll sein, wenn diese ganzzahlig und nicht zu groß sind.
Semantik (Wert) bei Vergleichen von Laufzeitwerten
Obwohl in dem folgenden Programm beide Operanden »global::Microsoft.JScript.MathObject.random()« (als Quelltext) genau gleich sind, ergibt der Vergleich doch »False«.
Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine
( global::Microsoft.JScript.MathObject.random() ==
global::Microsoft.JScript.MathObject.random() ); }}Protokoll
False
Dies liegt daran, daß jede Auswertung des Ausdrucks »global::Microsoft.JScript.MathObject.random()« einen neuen Laufzeitwert ergibt, der sich von dem Wert einer anderen Auswertung desselben Ausdrucks unterscheiden kann.
Semantik (Wert) bei String==String-Vergleichen
Zwei Zeichenfolgen gelten als einander gleich, wenn sie genau gleich viele Zeichen enthalten und jedes Zeichen der ersten Zeichenfolge genau gleich zu dem Zeichen der zweiten Zeichenfolge ist, das sich an derselben Stelle befindet.
Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine( "abc" == "abc" );
global::System.Console.WriteLine( "abc" == "abc " );
global::System.Console.WriteLine( "abc" == "Abc" ); }}Protokoll
True
False
False
Semantik (Wert) bei bool==bool-Vergleichen
Wahrheitswerte können ohne weiteres verglichen werden. Man erhält die erwarteten Ergebnisse.
Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine( true == false );
global::System.Console.WriteLine( false == false ); }}Protokoll
False
True
Der Operator »==« ist linksassoziativ. Entsprechend bedeutet »false == false == false« beispielsweise dasselbe wie »( false == false )== false«, also »true == false«, was »false« ergibt.
Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine( false == false == false );
global::System.Console.WriteLine( true == true == true ); }}Protokoll
False
True
Zur Auswertung von »false == false == false«:
- erste (linke) Gleichheitsaussage
_____________
false == false == false →
true == false- zweite Gleichheitsaussage
true == false →
false
Der Gleichheitsoperator »==« und der Zuweisungsoperator »=«
Man beachte die Unterscheidung zwischen dem Zuweisungsoperator »=« und dem Gleichheitsoperator »==«. Beide sind jeweils eine lexikalische Einheit, die erste schreibt sich jedoch mit einem Gleichzeichen »=«, die zweite mit zwei Gleichzeichen »==«.
Der Zuweisungsoperator »=« ist ein Wertwirkoperator, während der Gleichheitsoperator »==« ein reiner Wertoperator ist.
Selbst, wenn man dies weiß, ist es ein häufiger Flüchtigkeitsfehler, versehentlich statt »==« den Operator »=« zu verwenden. Manchmal wird »false == x« statt »x == false« geschrieben, da ersteres mit Sicherheit eine Fehlermeldung ergibt, wenn versehentlich ein Gleichheitszeichen weggelassen wird.
Wenn keine Verwechslungen mit einer Zuweisung zu befürchten sind, kann man den Operator »==« als „(ist) gleich“ aussprechen. Sind Verwechslungen zu befürchten, so muß er genauer als „Gleichheitsaussage“ oder ähnlich bezeichnet werden.
Die mathematische Schreibweise des Operators »==« ist ‹=› (ein einfaches Gleich-Zeichen). (Für die Java -Zuweisung »=« gibt es in der Mathematik keine genaue Entsprechung.)
Beispiele
● Gleiche Werte bei verschiedenen Ausdrücken
Wir können nun deutlich erkennen, daß verschiedene Ausdrücke den gleichen Wert haben können, was noch einmal den Unterschied zwischen Ausdrücken und Werten verdeutlicht.
Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine( 12.0 == 12.00 );
global::System.Console.WriteLine( 12 == +12 );
global::System.Console.WriteLine( 12 == 6+6 ); }}Protokoll
True
True
True
● Prädikate
In dem folgenden Programm wird ein Prädikat »ist_sieben« definiert, das es erlaubt, die Aussage zu schreiben, daß eine Zahl gleich Sieben sei.
Program.cs
public static class Program
{public static bool IstSieben( int zahl )
{ return 7 == zahl; }static void Main()
{ global::System.Console.WriteLine( IstSieben( 6 ));
global::System.Console.WriteLine( IstSieben( 7 ));
global::System.Console.WriteLine( IstSieben( 8 )); }}Protokoll
False
True
False
Übungsfragen
? Übungsfrage
Welche Ausgabe erzeugt das folgende Programm?
Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine( 2 == 2 ); }}
? Übungsfrage
Welche Ausgabe erzeugt das folgende Programm?
Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine( 2 == 3 ); }}
? Übungsfrage
Welche Ausgabe erzeugt das folgende Programm?
Program.cs
public static class Program
{ public static void Main()
{ global::System.Console.WriteLine( 3 == 2 + 1 ); }}
? Übungsfrage
Welche Ausgabe erzeugt das folgende Programm?
Program.cs
public static class Program
{public static void Method( int zahl )
{ global::System.Console.WriteLine( zahl == 0 ); }static void Main()
{ Method( 3 ); }}
? Übungsfrage
Welche Ausgabe erzeugt das folgende Programm?
Program.cs
public static class Program
{public static void Method( int zahl )
{ global::System.Console.WriteLine( zahl - 3 == 0 ); }static void Main()
{ Method( 2 + 1 );
Method( 2 + 0 ); }}
? Übungsfrage
Welche Ausgabe erzeugt das folgende Programm?
Program.cs
public static class Program
{public static bool Id( bool wert )
{ return wert; }static void Main()
{ global::System.Console.WriteLine( Id( false ));
global::System.Console.WriteLine( Id( true )); }}
? Übungsfrage
Welche Ausgabe erzeugt das folgende Programm?
Program.cs
public static class Program
{public static bool F( bool wert )
{ return true == wert; }static void Main()
{ global::System.Console.WriteLine( F( false ));
global::System.Console.WriteLine( F( true )); }}
? Übungsfrage
Welche Ausgabe erzeugt das folgende Programm?
Program.cs
public static class Program
{public static bool F( bool wert )
{ return false == wert; }static void Main()
{ global::System.Console.WriteLine( F( false ));
global::System.Console.WriteLine( F( true )); }}
? Übungsfrage
Welche Ausgabe erzeugt das folgende Programm?
Program.cs
public static class Program
{public static void Method( int zahl )
{ global::System.Console.WriteLine( 3 == zahl == false ); }static void Main()
{ Method( 2 + 0 );
Method( 2 + 1 ); }}
? Übungsfrage *
Welche Ausgabe erzeugt das folgende Programm?
Program.cs
public static class Program
{ public static void Main()
{ bool wert = false;
global::System.Console.WriteLine( wert = wert == false ); }}
? Übungsfrage *
Ergibt die im folgenden deklarierte Methode »M« immer true ?
Program.cs
public static bool M( int a )
{ return global::System.Math.Abs( -a )== a; }
? Übungsfrage *
Program.cs
public static class Program
{ public static void Main()
{ bool a = false;
bool b = true;
bool c = false;
bool d = true;
global::System.Console.WriteLine( a = b = c == d );
global::System.Console.WriteLine( a = b == c == d ); }}
Übungsaufgaben *
/ Nulldetektor
Schreiben Sie eine Methode »IsZero(int)«, die genau dann »true« ergibt, wenn sie mit »0« aufgerufen wird.
Dazu soll die Ellipse in dem folgenden Programmrahmen durch einen geeigneten Text ersetzt werden.
Wenn die Methode richtig geschrieben wurde, gibt das Programm immer nur »True« aus.
Program.cs
public static class Program
{public static bool IsZero( int zahl )
{ _________ }static void Main()
{ global::System.Console.WriteLine( IsZero( 0 )== true );
global::System.Console.WriteLine( IsZero( 1 )== false );
global::System.Console.WriteLine( IsZero( -1 )== false );
global::System.Console.WriteLine( IsZero( 2 )== false );
global::System.Console.WriteLine( IsZero( -2 )== false ); }}
/ Umwandlung *
Schreiben Sie eine Methode »Boolean(int)«, die von »int« nach »bool« „wandelt“. Sie soll für den Argumentwert »0« das Ergebnis false haben und sonst immer true ergeben.
Wenn die Methode in den folgenden Testrahmen eingesetzt wird, soll immer nur »true« ausgegeben werden.
Program.cs
public static class Program
{public static bool Boolean( int zahl )
{ __________ }static void Main()
{ global::System.Console.WriteLine( Boolean( 0 )== false );
global::System.Console.WriteLine( Boolean( 1 )== true );
global::System.Console.WriteLine( Boolean( -1 )== true );
global::System.Console.WriteLine( Boolean( 2 )== true );
global::System.Console.WriteLine( Boolean( -2 )== true ); }}
/ Teilbarkeitsprädikat *
Schreiben Sie eine Methode »VierTeilt«, die dann und nur dann »true« ergibt, wenn ihr int-Argument durch »4« teilbar ist.
(Es reicht, wenn diese Methode für nicht-negative Werte das richtige Ergebnis liefert.)
Wenn die Methode in den folgenden Testrahmen eingesetzt wird, soll immer nur »true« ausgegeben werden.
Program.cs
public static class Program
{__________
static void Main()
{ global::System.Console.WriteLine( VierTeilt( 0 )== true );
global::System.Console.WriteLine( VierTeilt( 1 )== false );
global::System.Console.WriteLine( VierTeilt( 2 )== false );
global::System.Console.WriteLine( VierTeilt( 3 )== false );
global::System.Console.WriteLine( VierTeilt( 4 )== true );
global::System.Console.WriteLine( VierTeilt( 5 )== false );
global::System.Console.WriteLine( VierTeilt( 6 )== false );
global::System.Console.WriteLine( VierTeilt( 7 )== false );
global::System.Console.WriteLine( VierTeilt( 8 )== true );
global::System.Console.WriteLine( VierTeilt( 9 )== false ); }}Protokoll
True
True
True
True
True
True
True
True
True
True
/ Prädikate *
Schreiben Sie folgende Prädikate (Methodendeklarationen):
- »isZero(int)« ergibt »true« genau dann, wenn der Argumentwert gleich »0« ist.
- »isNotZero(int)« ergibt »true« genau dann, wenn der Argumentwert nicht gleich »0« ist.
- »isNotEqual(int,int)« ergibt »true« genau dann, wenn beide Argumentwerte nicht einander gleich sind.
- »isLessThan(int,int)« ergibt »true« genau dann, wenn der erste Argumentwert kleiner als der zweite ist. (Das dürfte schwierig werden, es reicht, wenn das Ergebnis für Argumentwerte zwischen 1 [einschließlich] und 10000 [einschließlich] stimmt.)
- »isLessThanOrEqual(int,int)« ergibt »true« genau dann, wenn der erste Argumentwert kleiner als der zweite oder gleich dem zweiten ist. (Es gilt hier ebenfalls das bei der vorigen Aufgabe in den Klammern Gesagte.)
- »XOR(bool,bool)« ergibt »true« dann, wenn der erste Argumentwert oder der zweite Argumentwert wahr ist, aber »false«, wenn keiner oder beide wahr sind.
Es dürfen nur die im Kurs bisher schon vorgestellten Sprachelemente verwendet werden!
Das Zuweisungsprinzip *
Das Zuweisungsprinzip stellt eine Beziehung zwischen dem Operator »=« und dem Operator »==« her: direkt nach einer Zuweisung an eine Variable ergibt ein Vergleich der Variablen mit dem zugewiesenen Wert true.
Program.cs
public static class Program
{ public static void Main()
{ int v;
v = 2;
global::System.Console.WriteLine( v == 2 ); }}Protokoll
True