C#.NET * C++ * JAVASCRIPT * PYTHON * DIVERSES
XML * XML-SCHEMA * XPATH * XSL * XSL-FO * SVG * XQUERY * XPROC * ANT



C#.NET / C#.NET Grundlagen / C#.NET Einfache Datentypen

C#.NET Einfache Datentypen

C#.NET Einfache Datentypen

➪ Diese Seite bietet einen Überblick über wichtige simple Datentypen und deren grundlegende Formatierungsmöglichkeiten.

Auf dieser Seite:

In jeder Programmiersprache sind Variablen von elementarer Bedeutung. Variable werden in unterschiedliche Typen eingeteilt, hier ist ein erster Überblick hilfreich.

Für den Einstieg ist es sinnvoll, den Typ einer Variablen bereits im Quellcode verbindlich festzulegen und damit eine verläßliche Programmstabilität technisch zu erzwingen. (Das muss aber nicht immer so sein: Auch in C#.NET kann es vorkommen, dass Typ einer Variablen erst zur Laufzeit automatisch zugewiesen wird.)

Byte Ganzzahl zwischen 0 (Byte.MinValue) und 255 (Byte.MaxValue)
SByte Ganzzahl zwischen -128 (SByte.MinValue) und 127 (SByte.MaxValue)
short Ganzzahl (Int16) zwischen -32768 (short.MinValue) und 32767 (short.MaxValue)
ushort Ganzzahl (UInt16) zwischen 0 (ushort.MinValue) und 65535 (ushort.MaxValue)
int Ganzzahl (Int32) zwischen -2147483648 (int.MinValue) und 2147483647 (int.MaxValue)
uint Ganzzahl (UInt32) zwischen 0 (uint.MinValue) und 4294967295 (uint.MaxValue)
long Ganzzahl (Int64) zwischen -9223372036854775808 (long.MinValue) und 9223372036854775807 (long.MaxValue)
ulong Ganzzahl (UInt64) zwischen 0 (ulong.MinValue) und 18446744073709551615 (ulong.MaxValue)
System.Numerics.BigInteger Stellt eine beliebig große Ganzzahl mit Vorzeichen dar.
float Gleitkommazahl mit einfacher Genauigkeit zwischen -3,402823E+38 (float.MinValue) und 3,402823E+38 (float.MaxValue)
double Gleitkommazahl mit doppelter Genauigkeit zwischen -1,79769313486232E+308 (double.MinValue) und 1,79769313486232E+308 (double.MaxValue)
decimal Gleitkommazahl mit hoher Genauigkeit zwischen -79228162514264337593543950335 (decimal.MinValue) und 79228162514264337593543950335 (decimal.MaxValue)

Hinter jeder Variablen steht ein Bereich im Arbeitsspeicher; der Name der Variablen dient (quasi als Alias) dazu, diesen Speicherbereich anzusprechen.

Beginnen Sie, indem Sie eine int-Variable deklarieren und mit einem Wert initialisieren. Anschließend geben Sie diesen Wert mithilfe der Console aus.


int i = 1234567890;
Console.WriteLine(i);
Console.WriteLine("{0}", i);
Console.WriteLine("{0:N2}", i);
Console.WriteLine("{0,45}", i);
Console.WriteLine("{0,45:N2}", i);
{0} ist der Platzhalter für den ersten Parameter nach dem Komma.
{0:N2} formatiert in Tausender-Gruppierung mit zwei Nachkommastellen.
{0,45} formatiert eine Zeichenkette mit 45 Zeichen, rechtsbündig.
{0,45:N2} formatiert eine Zeichenkette mit 45 Zeichen, rechtsbündig, in Tausender-Gruppierung mit zwei Nachkommastellen.

Alternativ können Sie die Variable i auch in verkürzter Syntax ausgeben:


Console.WriteLine($"{i}");
Console.WriteLine($"{i:N2}");
Console.WriteLine($"{i,45}");
Console.WriteLine($"{i,45:N2}");

Der vorstehende Aufruf hat dieses Ergebnis:


1234567890
1234567890
1.234.567.890,00
                                   1234567890
                             1.234.567.890,00  

Diese Formatierungsalternativen können Sie verwenden, um die Minimal- und Maximalwerte einfacher Ganzzahlen anschaulich darstellen zu können.


Console.WriteLine("Int16.MinValue           : {0,27:N0}", Int16.MinValue);
Console.WriteLine("Int16.MaxValue           : {0,27:N0}", Int16.MaxValue);
Console.WriteLine("UInt16.MinValue          : {0,27:N0}", UInt16.MinValue);
Console.WriteLine("UInt16.MaxValue          : {0,27:N0}", UInt16.MaxValue);
Console.WriteLine("Int32.MinValue           : {0,27:N0}", Int32.MinValue);
Console.WriteLine("Int32.MaxValue           : {0,27:N0}", Int32.MaxValue);
Console.WriteLine("UInt32.MinValue          : {0,27:N0}", UInt32.MinValue);
Console.WriteLine("UInt32.MaxValue          : {0,27:N0}", UInt32.MaxValue);
Console.WriteLine("Int64.MinValue           : {0,27:N0}", Int64.MinValue);
Console.WriteLine("Int64.MaxValue           : {0,27:N0}", Int64.MaxValue);
Console.WriteLine("UInt64.MinValue          : {0,27:N0}", UInt64.MinValue);
Console.WriteLine("UInt64.MaxValue          : {0,27:N0}", UInt64.MaxValue);

Ergebnis:


Int16.MinValue           :                     -32.768
Int16.MaxValue           :                      32.767
UInt16.MinValue          :                           0
UInt16.MaxValue          :                      65.535
Int32.MinValue           :              -2.147.483.648
Int32.MaxValue           :               2.147.483.647
UInt32.MinValue          :                           0
UInt32.MaxValue          :               4.294.967.295
Int64.MinValue           :  -9.223.372.036.854.775.808
Int64.MaxValue           :   9.223.372.036.854.775.807
UInt64.MinValue          :                           0
UInt64.MaxValue          :  18.446.744.073.709.551.615

Nullable Types


int? i = null;
i = 5;

System.Numerics.BigInteger

Neben den Standard-Datentypen, die im Namespace System definiert sind, gibt es noch erweiterte Datentypen im Namespace System.Numerics, den Sie über Verweise/Verweis hinzufügen einbinden können.

pic/cs_verweis.png

pic/cs_verweis_system_numerics.png

BigInteger stellt eine beliebig große Ganzzahl mit Vorzeichen dar. Diese kann die Größe von UInt64.MaxValue deutlich übersteigen, wie Sie an diesem Beispiel erkennen können.


BigInteger bigint;
bigint = BigInteger.Parse("1844674407370955161518446744073709551615");
Console.WriteLine($"{bigint:N2}");
bigint = bigint * bigint;
Console.WriteLine($"{bigint:N2}");

Vorteilhaft sind auch die Pow-Methode und die IsPowerOfTwo-Eigenschaft.


bigint = BigInteger.Pow(2, 60);
Console.WriteLine("{0:N2}", bigint);
if (bigint.IsPowerOfTwo) 
    Console.WriteLine("{0} ist ein Vielfaches von 2", bigint);
IsEven Prüft, ob der Wert eine gerade Zahl ist.
IsOne Prüft, ob der Wert die Zahl 1 ist.
IsPowerOfTwo Prüft, ob der Wert ein Vielfaches von 2 ist.
IsZero Prüft, ob der Wert die Zahl 0 ist.
Sign Gibt das Vorzeichen des Wertes zurück.

Was etwa im Integer-Bereich über den Modulo-Operator erfolgt (1 = 15 % 2;), nämlich die Berechnung des ganzzahligen Restes einer Division, können Sie im BigInteger-Kontext mit BigInteger.DivRem erledigen. Hier liefert DivRem sowohl das ganzzahlige Ergebnis der Division als auch den ganzzahligen Rest zurück.


bigint = 35;
BigInteger rest = new BigInteger();
BigInteger ergebnis = BigInteger.DivRem(bigint, 9, out rest);
Console.WriteLine("Die Division von {0} / 9 ergibt {1} Rest {2}", 
                   bigint, ergebnis, rest);

Wenn Sie nur den Rest haben möchten und das tatsächliche Ergebnis der Division keine Rolle spielt, kommen Sei auch mit BigInteger.Remainder klar:


rest = BigInteger.Remainder(bigint, 9);
Console.WriteLine("BigInteger.Remainder: {0}", rest);

Interessant ist auch die Arbeit mit dem BigInteger.GreatestCommonDivisor, der den größten gemeinsamen Teiler zweier BigInteger-Zahlen ermittelt.


BigInteger bi1 = BigInteger.Pow(2, 30);
BigInteger bi2 = BigInteger.Pow(4, 10);
BigInteger bi_ggt = BigInteger.GreatestCommonDivisor(bi1, bi2);
Console.WriteLine("BigInteger.GreatestCommonDivisor: {0}", bi_ggt);
// Ergebnis: 
// BigInteger.GreatestCommonDivisor: 1048576

Weitere Formatierungsalternativen

Neben N0 gibt es natürlich auch andere Formatierungsalternativen.


Console.WriteLine("N2 mit Nachkommastellen : {0,45:N2}", Int64.MaxValue);
Console.WriteLine("C für Währungen         : {0,45:C}",  Int64.MaxValue);
Console.WriteLine("E für Exponentialwerte  : {0,45:E}",  Int64.MaxValue);
Console.WriteLine("F für fixed-point       : {0,45:F5}", Int64.MaxValue);
Console.WriteLine("X für Hexadezimalwerte  : {0,45:X}",  Int64.MaxValue);
Console.WriteLine("G für allgemeines Format: {0,45:G}",  Int64.MaxValue);
Console.WriteLine("P für Prozentualwerte   : {0,45:P}",  Int64.MaxValue);

Das Ergebnis sieht auf Console so aus:


N2 mit Nachkommastellen :                  9.223.372.036.854.775.807,00
C für Währungen         :                9.223.372.036.854.775.807,00 ?
E für Exponentialwerte  :                                 9,223372E+018
F für fixed-point       :                     9223372036854775807,00000
X für Hexadezimalwerte  :                              7FFFFFFFFFFFFFFF
G für allgemeines Format:                           9223372036854775807
P für Prozentualwerte   :              922.337.203.685.477.580.700,00 %

Double: Doppelgenaue Zahlen mit Nachkommastellen

Ähnliche Formatierungsmöglichkeiten stehen Ihnen auch beim Datentyp Double zu.


Console.WriteLine("Double.MinValue         : {0,45:N2}", Double.MinValue);
Console.WriteLine("Double.MaxValue         : {0,45:N2}", Double.MinValue);            
Console.WriteLine("R Round-trip für Double : {0,45:R}",  Double.MaxValue);
double d = 0.57;
Console.WriteLine(d.ToString("000.000,00000"));
Console.WriteLine(d.ToString("#,##0.00"));

Double: Hochgenaue Zahlen mit Nachkommastellen

Dasselbe gilt für den Datentyp Decimal:


Console.WriteLine("Decimal.MinValue        : {0,45:N2}", Decimal.MinValue);
Console.WriteLine("Decimal.MaxValue        : {0,45:N2}", Decimal.MinValue);

Vergleich float, double und decimal

Sie haben nun die Zahlentypen float, double und decimal kennengelernt. Hierbei handelt es sich jeweils um Zahlentypen mit Nachkommastellen, jedoch mit unterschiedlicher Genauigkeit. Was heißt das aber?

Sie können sich die Sache so vorstellen, dass das System versucht, eine Nachkommazahl durch einen internen Algorithmus abzubilden. Dieser Algorithmus ist je nach Zahlentyp unterschiedlich.

Auch auf die Gefahr hin, inhaltlich vorzugreifen, wenn ich schon hier das Thema Schleifen berühre, möchte ich mehrere Multiplikationen von float/double/decimal-Zahlen durchführen und die Ergebnisse vergleichen. Zunächst das Beispiel für float:


float p2      = 3;
// Das System erwartet den Suffix F, 
// um die Zahl als Float zu kennzeichnen
for (float p1 = 2.90F; p1 < 3; p1 = (float)(p1 + 0.01))
{
    float p3 = p1 * p2;
    Console.WriteLine("{0} * {1} = {2}", p1, p2, p3);
}

Die Ergebnisse lauten, nicht durchweg befriedigend:


2,9  * 3 = 8,700001
2,91 * 3 = 8,73
2,92 * 3 = 8,76
2,93 * 3 = 8,79
2,94 * 3 = 8,82
2,95 * 3 = 8,85
2,96 * 3 = 8,88
2,97 * 3 = 8,91
2,98 * 3 = 8,940001
2,99 * 3 = 8,97

Der doppeltgenaue Versuch mit double hat diesen Ansatz:


double p2      = 3;
for (double p1 = 2.90; p1 < 3; p1 = p1 + 0.01)
{
    double p3 = p1 * p2;
    Console.WriteLine("{0} * {1} = {2}", p1, p2, p3);
}

Die Ergebnisse sind nicht überzeugend besser:


2,9  * 3 = 8,7
2,91 * 3 = 8,73
2,92 * 3 = 8,76
2,93 * 3 = 8,79
2,94 * 3 = 8,82
2,95 * 3 = 8,85
2,96 * 3 = 8,88
2,97 * 3 = 8,90999999999999
2,98 * 3 = 8,93999999999999
2,99 * 3 = 8,96999999999999
3    * 3 = 8,99999999999999

Zum Schluß sehen Sie sich die hochgenauen Ergebnisse von decimal an:


decimal p2    = 3;
decimal steps = 0.01M;
// Das System erwartet den Suffix M, 
// um die Zahl als decimal zu kennzeichnen
for (decimal p1 = 2.90M; p1 < 3; p1 = decimal.Add(p1, steps))
{
    decimal p3 = p1 * p2;
    Console.WriteLine("{0} * {1} = {2}", p1, p2, p3);
}

Die Ergebnisse liegen nun deutlich näher an den Resultaten, die ich erwartet habe:


2,90 * 3 = 8,70
2,91 * 3 = 8,73
2,92 * 3 = 8,76
2,93 * 3 = 8,79
2,94 * 3 = 8,82
2,95 * 3 = 8,85
2,96 * 3 = 8,88
2,97 * 3 = 8,91
2,98 * 3 = 8,94
2,99 * 3 = 8,97

Arbeiten mit Steuerzeichen

In der Formatierungsanweisung können auch spezielle Steuerzeichen verwendet werden.


// \n: Zeilenvorschub
// \t: Tabulatorvorschub
string s = "Hallo Leute von heute";
string sformat = "Freundliche Gruesse: \n\t{0}\nEinen schönen Tag noch";
Console.WriteLine(sformat, s);

Datumswerte

Ein weiterer häufig verwendeter Datentyp ist DateTime


DateTime jetzt = DateTime.Now;
Console.WriteLine($"Kurzes Datumsformat     : {jetzt:d}");
Console.WriteLine($"Langes Datumsformat     : {jetzt:D}");
Console.WriteLine($"Langes Datum, kurze Zeit: {jetzt:f}");
Console.WriteLine($"Langes Datum, lange Zeit: {jetzt:F}");
Console.WriteLine($"Kurzes Datum, kurze Zeit: {jetzt:g}");
Console.WriteLine($"Kurzes Datum, lange Zeit: {jetzt:G}");
Console.WriteLine($"Kurzes Zeitformat       : {jetzt:t}");
Console.WriteLine($"Langes Zeitformat       : {jetzt:T}");
Console.WriteLine($"ISO-Zeitformat          : {jetzt:u}");
Console.WriteLine($"Langes ISO-Zeitformat   : {jetzt:U} 
                                              (UTC-Zeitverschiebung!)");
Console.WriteLine($"Format yyMMdd           : {jetzt:yyMMdd}");
Console.WriteLine($"Format  yyyy-dd-MM      : {jetzt:yyyy-dd-MM}");
Console.WriteLine($@"Individuelles Format    : {jetzt:MM\/dd\/yyyy}");
Console.WriteLine($"hh mm ss    : {jetzt:hh:mm:ss}");
DateTime spaeter = jetzt.AddHours(4560);
Console.WriteLine($"4560 Stunden spaeter    : {spaeter:yyyyMMdd_hh:mm:ss}");

An jenem Zeitpunkt, wo ich das geschrieben habe, lautete das Ergebnis des Aufrufs:


Kurzes Datumsformat     : 25.01.2019
Langes Datumsformat     : Freitag, 25. Januar 2019
Langes Datum, kurze Zeit: Freitag, 25. Januar 2019 09:53
Langes Datum, lange Zeit: Freitag, 25. Januar 2019 09:53:54
Kurzes Datum, kurze Zeit: 25.01.2019 09:53
Kurzes Datum, lange Zeit: 25.01.2019 09:53:54
Kurzes Zeitformat       : 09:53
Langes Zeitformat       : 09:53:54
ISO-Zeitformat          : 2019-01-25 09:53:54Z
Langes ISO-Zeitformat   : Freitag, 25. Januar 2019 08:53:54 
                          (UTC-Zeitverschiebung!)
Format yyMMdd           : 190125
Format  yyyy-dd-MM      : 2019-25-01
Individuelles Format    : 01/25/2019
hh mm ss                : 09:53:54
4560 Stunden spaeter    : 20190803_09:53:54

wg / 4. April 2021



Fragen? Anmerkungen? Tipps?

Bitte nehmen Sie Kontakt zu mir auf.






Vielen Dank für Ihr Interesse an meiner Arbeit.



V.i.S.d.P.: Wilfried Grupe * Klus 6 * 37643 Negenborn

☎ 0151. 750 360 61 * eMail: info10@wilfried-grupe.de

www.wilfried-grupe.de/CS_Datentypdemo_Formatierungen.html