2 Einfache Rechnungen 2.1 Zahlen Computer, auch bekannt als Rechner, sind sinnvoller eingesetzt, wenn sie nicht nur feste Texte ausgeben, sondern eben auch rechnen. Um das Rechnen mit Zahlen zu verstehen, schauen wir uns zunächst die Darstellung von Zahlen an. 2.1.1 Zahlendarstellung in verschiedenen Basen In der gewöhnlichen Dezimaldarstellung geben die Ziffern die Anzahl von Einern, Zehnern, Hundertern usw. also Zehnerpotenzen an. So bedeutet die Ziffernfolge 206 als Dezimalzahl 2 10 2 + 0 10 1 + 6 10 0 = 206. Binärzahlen funktionieren genauso, nur hat man Zwei als Basis anstatt Zehn. Somit bedeutet die Ziffernfolge 101010 1 2 5 + 0 2 4 + 1 2 3 + 0 2 2 + 1 2 1 + 0 2 0 = 42. Die Ziffernfolge 213 als Oktalzahl (Basis Acht) bedeutet 2 8 2 + 1 8 1 + 3 8 0 = 139. Hexadezimalzahlen haben die Basis Sechzehn und benutzen als zusätzliche Ziffern A (für 10) bis F (für 15). Somit bedeutet die Ziffernfolge 1D3 1 16 2 + 13 16 1 + 3 16 0 = 467. 2-1
2 Einfache Rechnungen 1. November 2010 2.1.2 Zahlen im Computer Im Computer werden Werte in Bytes, das sind heutzutage acht Bit, gespeichert. Damit kann dann eine achtstellige Binärzahl dargestellt werden. Es können auch mehrere Byte zusammengefasst werden, so ergeben zwei Byte eine 16-stellige Binärzahl und vier Byte eine 32-stellige. Letztere kann Zahlen von 0 bis 2 32 1 aufnehmen. Für die Darstellung vorzeichenbehafteter Zahlen gibt es verschiedene Möglichkeiten. Bei der Darstellung im Zweierkomplement steht das höchste Bit nicht für 2 n 1, sondern für 2 n 1. Damit ist jede Zahl, deren höchstes Bit gesetzt ist, negativ. Es ist sichergestellt, dass die Darstellung vorzeichenbehafteter positiver Zahlen mit der Darstellung vorzeichenloser Zahlen übereinstimmt. 2.1.3 Ganzzahltypen Mit Typen wird angegeben, wieviel Speicher für einen Wert reserviert wird, und wie er interpretiert wird. Wir haben schon bei hello world gesehen, wie bei der Hauptfunktion als Ergebnistyp int angegeben wurde. int ist der Standardtyp für vorzeichenbehaftete ganzzahlige Werte. Es gibt verschiedene Variationen von int, die sich in der Größe des benutzten Speichers und damit im erlaubten Wertebereich unterscheiden. Der C-Standard schreibt Mindestgrößen vor. Solange diese eingehalten werden, dürften diese Typen auch gleich groß sein. Die Typen sind: short int (oder einfach short) umfasst mindestens 16 Bit int umfasst auch mindestens 16 Bit long int (oder einfach long) umfasst mindestens 32 Bit (In C99 gibt es auch noch long long mit mindestens 64 Bit.) Dazu kann noch angegeben werden, ob der Typ vorzeichenbehaftet ist oder nicht. Dazu schreibt man vor den Typen noch unsigned für vorzeichenlose Zahlen oder signed für vorzeichenbehaftete. Ohne eine solche Angabe ist der Typ vorzeichenbehaftet. Es gibt also einige Typbezeichnungen für denselben Typ. Zum Beispiel gibt es keinen Unterschied zwischen signed long int, signed long, long int und long. 2-2
1. November 2010 2.2 Variablen und Zuweisungen 2.2 Variablen und Zuweisungen Variablen sind Werte, die während des Programmablaufes verändert werden können. Damit für sie Speicher reserviert werden kann, müssen sie in C zuvor definiert werden, wobei ihr Typ angegeben werden muss. Dazu schreibt man zunächst den Typ und dann den Namen der Variablen hin, gefolgt von einem Semikolon. Zum Beispiel wird durch int x; die Variable x von Typ int definiert. Als Name kommt jeder in C zulässige Bezeichner in Frage. Bezeichner sind eine Folge von Buchstaben, Zahlen und Unterstrichen, die nicht mit einer Zahl anfängt. Allerdings darf kein Schlüsselwort (wie z.b. long oder signed) benutzt werden, und kein Bezeichner, der schon für etwas anderes benutzt wird. So darf printf nur benutzt werden, wenn das Programm ausnahmsweise nicht die Zeile #include <stdio.h> enthält und auch dann ist es nicht ratsam. Um nun einer Variablen einen Wert zuzuweisen, schreibt man erst den Namen dieser Variablen, dann ein Gleichheitszeichen, und dann den Wert, den die Variable aufnehmen soll. Dieser Wert kann ein beliebig komplizierter Ausdruck sein. Beendet wird die Zuweisung mit einem Semikolon. x = 6*6+8*8; /* x erhält den Wert 100 */ x = x+1; /* x wird um 1 erhöht */ Die zweite Zuweisung im Beispiel, die für Mathematiker einen Kulturschock darstellen kann, ist in Wahrheit ganz harmlos. Es handelt sich nicht um eine unlösbare Gleichung, sondern um die Anweisung, den Wert der Variablen x zu nehmen, 1 zu addieren, und das Ergebnis wieder in der Variablen x zu speichern. (Andere Programmiersprachen nehmen für die Zuweisung weniger irritierende Notationen als das Gleichheitszeichen, so nimmt Pascal := und in Pseudocode wird gerne benutzt.) 2.3 Ein kleines Beispielprogramm Um den Wert einer Variablen auszugeben, kann man die Funktion printf benutzen. Die Zeichenkette, die ihr übergeben wird, wird nämlich nicht unbedingt einfach so ausgegeben. Wenn in ihr %d vorkommt, so muss der Funktion printf ein int-wert als zweites Argument übergeben werden, der als Dezimalzahl an Stelle von %d ausgegeben wird. Man kann auch mehrere %d in der Zeichenkette haben, dann braucht man auch entsprechend viele weitere int-werte als Argumente. 2-3
2 Einfache Rechnungen 1. November 2010 printf( "Der Wert von x ist %d.\n", x ); printf( "%d und %d ist %d\n", 2, 3, 2+3 ); Wir simulieren jetzt einen albernen Zahlentrick, bei der man sich eine Zahl ausdenken soll, sie zu sich selbst addiert, zwölf hinzuzählt, das ganze halbiert, und die ursprüngliche Zahl abzieht. Der vermeintliche Gedankenleser und der Mathematiker kennen das Ergebnis. /* Zahlentrick */ #include <stdio.h> int main( void ) { int zahl; /* die gedachte Zahl */ int wert; /* für die weiteren Rechnungen */ zahl = 23; /* beliebige Zahl */ wert = zahl + zahl; /* zahl mit sich selbst addiert */ wert = wert + 12; /* zwölf hinzugezählt */ wert = wert / 2; /* das ganze halbiert */ wert = wert - zahl; /* ursprüngliche Zahl abgezogen - immer sechs! */ } printf( "Ursprüngliche Zahl: %d\nergebnis: %d\n", zahl, wert ); return 0; Sie sehen hier auch, wie eine printf-anweisung mehrere Zeilen ausgeben kann. 2.4 Oktal- und Hexadezimalzahlen in C Neben der Dezimaldarstellung sind im Programmtext und als Ausgabe auch Oktal- und Hexadezimaldarstellung möglich. Wenn eine Zahl im Programm mit 0 anfängt, so wird sie als Oktalzahl interpretiert. Um eine Hexadezimalzahl einzugeben, schreibt man 0x oder 0X davor. In einem C-Programm bedeuten somit 63, 077 und 0x3f dasselbe. Für die Ausgabe muss lediglich bei printf eine andere Formatierungsangabe gewählt werden. Ist u eine Variable vom Typ unsigned int, so wird sie durch printf( "\%o", i ) als Oktalzahl und durch printf( "\%x", i ) als Hexadezimalzahl ausgegeben. 2-4
1. November 2010 2.5 Fließkommazahlen 2.5 Fließkommazahlen Es gibt die folgenden Fließkommatypen: float double long double Die Typen unterscheiden sich (möglicherweise) sowohl in der größten darstellbaren Zahl als auch in ihrer Genauigkeit. Der Name float erinnert an Fließkommazahl (floating point number), double steht (aus historischen Gründen) für doppelt genaue Fließkommazahlen und ist der Typ, der normalerweise für Fließkommazahlen genommen wird. Wenn im Programm eine Fließkommazahl erwartet wird, aber ein ganzzahliger Ausdruck dasteht, wird automatisch umgewandelt. Fließkommazahlen werden im Programmtext mit Dezimalpunkt und/oder Exponent (wissenschaftliche Schreibweise wie bei manchen Taschenrechnern) angegeben, z.b 12.3 oder 13e8 (für 13 10 8 ). Es sind dann double-werte, für float oder long double hängt man noch ein f bzw. l an. Auch Fließkommazahlen können mit printf ausgegeben werden. Dazu dienen die Formatierungsanweisungen %f, %e, %E, %g und %G. Für long double kommt zwischen die beiden Zeichen der Formatierungsanweisung noch ein L. Was die unterschiedlichen Formatierungsanweisungen machen, sollten Sie mit unterschiedlich großen Zahlen einmal ausprobieren. 2.6 Arithmetische Operatoren 2.6.1 Addition, Subtraktion und Multiplikation Die Operatoren +, - und * funktionieren wie erwartet und schon gesehen. Dabei gilt wie üblich Punkt- vor Strichrechnung, und es können Klammern gesetzt werden. Wenn bei einem unsigned-typ mit n Bit der Wertebereich verlassen wird, so erhält man das Ergebnis modulo 2 n. (Bei einem zu großen Ergebnis bedeutet das einfach, dass die nicht darstellbaren höchsten Bits abgeschnitten werden.) Wird bei einem anderen Typ der Wertebereich verlassen, ist das Ergebnis undefiniert. 2-5
2 Einfache Rechnungen 1. November 2010 2.6.2 Division und Modulo-Operator Die Division erfolgt mit /. Falls beide Operanden ganzzahlig sind, wird auch das Ergebnis zu einer ganzen Zahl gerundet. Nach dem C99-Standard werden die Nachkommastellen abgeschnitten, es wird also in Richtung Null gerundet. Früher war nur festgelegt, dass im Falle von positiven Zahlen abgerundet wird. Den Rest bei Division von a und b erhält man durch a % b. Diese Operation ist nur für ganzzahlige Operatoren erlaubt. Es ist immer a gleich (a/b)*a + (a%b). Somit ist bei positiven Operatoren auch das Ergebnis des Modulo-Operators positiv oder Null, und der Betrag von a%b ist kleiner als der von b. Beispiele: 7 % 3 ist 1, -7 % 3 ist -1, falls die Division dem C99-Standard entspricht, und sonst 2. 2-6