Die Tagesanzeige der Wetterstation
AFB I–IIDie Wetter-AG betreibt auf dem Schuldach eine kleine Wetterstation. Mira schreibt ein C-Programm, das auf dem Display im Foyer eine Tageszusammenfassung zeigt. Heute wurden vier Temperaturen gemessen: 19 °C, 22 °C, 24 °C und 18 °C. Zum Testen trägt Mira die Werte fest im Programm ein.
#include <stdio.h> int main(void) { int summe = 83; // vier Messwerte in °C: 19 + 22 + 24 + 18 int anzahl = 4; double mittel = summe / anzahl; char einheit = 'C'; int regen = 35; // Regenwahrscheinlichkeit in Prozent printf("Messungen:%5d\n", anzahl); printf("Mittel:%8.2f %c\n", mittel, einheit); printf("Regen:\t%d%%\n", regen); return 0; }
Beim ersten Test wundert sich Mira: Der Mittelwert sollte doch 20,75 °C sein.
- Ermitteln Sie die genaue Ausgabe des Programms. Kennzeichnen Sie jedes Leerzeichen mit dem Zeichen ␣ und den Tabulator mit →.
- Begründen Sie, warum beim Mittelwert nicht 20.75 erscheint, obwohl
mittelalsdoubledeklariert ist. - Nennen Sie zwei verschiedene Änderungen der Zeile
double mittel = summe / anzahl;, nach denen 20.75 ausgegeben wird.
Hinweise
Hinweis zu Aufgabe a)
printf-Aufrufe einzeln durch. %5d reserviert 5 Zeichen, %8.2f reserviert 8 Zeichen inklusive Punkt und Nachkommastellen; der Wert steht rechtsbündig. Was macht %%?Hinweis zu Aufgabe b)
summe und anzahl? In welcher Reihenfolge passieren Rechnen und Speichern in mittel?Hinweis zu Aufgabe c)
Erwartungshorizont
Erwartungshorizont zu Aufgabe a)
Messungen:␣␣␣␣4 Mittel:␣␣␣20.00␣C Regen:→35%
%5d: Die 4 ist eine Stelle breit, also 4 Leerzeichen davor.%8.2f:20.00ist 5 Zeichen breit, also 3 Leerzeichen davor; danach folgen das Leerzeichen aus dem Formatstring und das ZeichenC(%c).\tspringt zur nächsten Tabulatorposition (im Terminal meist Spalte 9),%%gibt ein einzelnes Prozentzeichen aus.
Erwartungshorizont zu Aufgabe b)
summe und anzahl sind beide int. Deshalb rechnet C 83 / 4 als Ganzzahldivision: Das Ergebnis ist 20, der Rest 3 (83 % 4) fällt weg. Erst danach wird die fertige 20 in die double-Variable gespeichert und zu 20.0 umgewandelt. Der Typ der Zielvariable ändert an der Rechnung nichts mehr.
Erwartungshorizont zu Aufgabe c)
double mittel = (double) summe / anzahl;— Typumwandlung (cast) vor der Divisiondouble mittel = summe / 4.0;— Kommazahl-Literal als Teiler- alternativ:
summegleich alsdouble summe = 83;deklarieren
Nicht richtig ist (double) (summe / anzahl): Hier wird erst ganzzahlig geteilt und dann 20 umgewandelt — Ausgabe weiterhin 20.00. Mit gcc geprüft: Die beiden ersten Varianten liefern 20.75.
Der Bon der Mensa-Kasse
AFB II–IIIDie Schülerfirma „Mampf & Co.“ programmiert eine einfache Kasse für die Mensa. Jonas und Aylin haben festgelegt: Alle Preise werden in Cent als int gespeichert, erst bei der Ausgabe wird in Euro umgerechnet. Schülerinnen und Schüler erhalten 10 % Rabatt auf den Gesamtbetrag; dabei wird auf ganze Cent abgeschnitten.
Die Preise: Nudelauflauf 3,95 €, Apfelschorle 1,50 €, Obstsalat 1,90 €. Für den ersten Test soll das Programm den Bon für eine Bestellung ausgeben, die genau so aussieht:
MENSA-KASSE Bon 0417 1 x Nudelauflauf 3.95 EUR 2 x Apfelschorle 3.00 EUR 1 x Obstsalat 1.90 EUR Summe 8.85 EUR Rabatt 10% -0.88 EUR Zu zahlen 7.97 EUR
Für den Rabatt haben die beiden zwei Zeilen im Gespräch: Jonas schreibt int rabatt = summe * 10 / 100;, Aylin int rabatt = summe / 100 * 10;.
Ein Lehrer rät: „Nehmt doch einfach double und rechnet gleich in Euro, das ist viel natürlicher.“ Aylin testet dazu printf("%.17f\n", 0.1 + 0.2); und erhält 0.30000000000000004.
- Implementieren Sie ein vollständiges C-Programm, das mit den Cent-Beträgen rechnet und den Bon genau wie in der Vorlage ausgibt (gleiche Spalten, gleiche Leerzeichen).
- Untersuchen Sie die beiden Rabatt-Zeilen von Jonas und Aylin für die Summe dieser Bestellung und für den allgemeinen Fall.
- Bewerten Sie die Entscheidung der Schülerfirma, Geldbeträge in Cent als
intstatt in Euro alsdoublezu speichern.
Hinweise
Hinweis zu Aufgabe a)
int-Variable in Cent an. Für die Euro-Ausgabe teilen Sie durch 100.0 (warum nicht durch 100?). Zählen Sie in der Vorlage, wie breit die Zahlenspalte ist, und wählen Sie die Feldbreite in %…f passend. Das Prozentzeichen im Formatstring braucht eine Sonderbehandlung.Hinweis zu Aufgabe b)
Hinweis zu Aufgabe c)
Erwartungshorizont
Erwartungshorizont zu Aufgabe a)
#include <stdio.h> int main(void) { int auflauf = 395; // Preise in Cent int schorle = 150; int obstsalat = 190; int summe = auflauf + 2 * schorle + obstsalat; int rabatt = summe * 10 / 100; // 10 % in ganzen Cent int zahlen = summe - rabatt; printf("MENSA-KASSE Bon 0417\n"); printf("1 x Nudelauflauf %8.2f EUR\n", auflauf / 100.0); printf("2 x Apfelschorle %8.2f EUR\n", 2 * schorle / 100.0); printf("1 x Obstsalat %8.2f EUR\n", obstsalat / 100.0); printf("Summe %8.2f EUR\n", summe / 100.0); printf("Rabatt 10%% %8.2f EUR\n", -rabatt / 100.0); printf("Zu zahlen %8.2f EUR\n", zahlen / 100.0); return 0; }
Die Ausgabe stimmt Zeichen für Zeichen mit der Vorlage überein. Wichtig: / 100.0 statt / 100 (sonst Ganzzahldivision, z. B. 395 / 100 = 3), %8.2f für die 8 Zeichen breite Zahlenspalte, %% für das Prozentzeichen. Andere Aufteilungen (z. B. eine Variable je Zeile) sind gleichwertig, wenn gerechnet statt abgeschrieben wird.
Erwartungshorizont zu Aufgabe b)
Summe: 395 + 2 · 150 + 190 = 885 Cent.
- Jonas:
885 * 10 / 100=8850 / 100= 88 Cent (exakt wären 88,5 Cent; abgeschnitten wie vereinbart). - Aylin:
885 / 100 * 10=8 * 10= 80 Cent — schon die erste Division wirft 85 Cent weg.
Allgemein: Bei Jonas geht erst im letzten Schritt höchstens ein Rest unter 1 Cent verloren, bei Aylin werden zuerst alle Cent unter einem vollen Euro abgeschnitten, sodass bis zu 9,9 Cent Rabatt fehlen können. Richtig ist Jonas’ Zeile; Faustregel: bei int erst multiplizieren, dann teilen. (Mit gcc geprüft: 88 bzw. 80.)
Erwartungshorizont zu Aufgabe c)
Für int in Cent spricht: Ganze Zahlen werden exakt gespeichert, Summen aus vielen Buchungen stimmen immer auf den Cent. Aylins Test zeigt, dass double schon 0,10 € und 0,20 € nicht exakt darstellen kann; bei vielen Additionen können sich solche Fehler bemerkbar machen, und Vergleiche wie „ist die Kasse ausgeglichen?“ werden unzuverlässig. Die Rundungsregel beim Rabatt lässt sich mit Ganzzahlen genau festlegen.
Dagegen spricht: Bei jeder Ausgabe muss umgerechnet werden (/ 100.0), und man muss die Ganzzahldivision im Blick behalten (siehe b). Beträge in Cent sind im Quelltext etwas schlechter lesbar.
Urteil: Für eine Kasse ist die Entscheidung gut begründet, weil Geldbeträge exakt stimmen müssen; der Mehraufwand ist gering. Vollständig ist die Bewertung mit mindestens zwei Kriterien, dem Bezug auf Aylins Testausgabe und einem klaren Urteil.
