4. Anwendungsaufgabe – IMPOTS
4.1. Die Aufgabe
Wir wollen ein Programm schreiben, mit dem sich die Steuer eines Steuerpflichtigen berechnen lässt. Wir betrachten den vereinfachten Fall eines Steuerpflichtigen, der nur sein Gehalt anzugeben hat:
- Die Anzahl der Anteile des Arbeitnehmers wird wie folgt berechnet: nbParts = nbEnfants/2 + 1, wenn er unverheiratet ist, nbEnfants/2+2, wenn er verheiratet ist, wobei nbEnfants die Anzahl seiner Kinder ist.
- Man berechnet sein zu versteuerndes Einkommen R = 0,72 * S, wobei S sein Jahresgehalt ist
- Man berechnet seinen Familienkoeffizienten Q = R/N
Man berechnet seine Steuer I anhand der folgenden Daten
12620,0 | 0 | 0 |
13.190 | 0,05 | 631 |
15640 | 0,1 | 1290,5 |
24.740 | 0,15 | 2072,5 |
31.810 | 0,2 | 3309,5 |
39.970 | 0,25 | 4900 |
48360 | 0,3 | 6898,5 |
55.790 | 0,35 | 9316,5 |
92.970 | 0,4 | 12106 |
127.860 | 0,45 | 16.754,5 |
151250 | 0,50 | 23.147,5 |
172.040 | 0,55 | 30.710 |
195.000 | 0,60 | 39312 |
0 | 0,65 | 49062 |
Jede Zeile enthält 3 Felder. Um die Steuer I zu berechnen, wird die erste Zeile gesucht, in der QF <= Feld 1 gilt. Wenn beispielsweise QF = 30000 ist, wird die Zeile
Die Steuer I beträgt dann 0,15*R – 2072,5*nbParts. Wenn QF so ist, dass die Beziehung QF <= Feld1 niemals erfüllt ist, werden die Koeffizienten der letzten Zeile verwendet. Hier:
was die Steuer I = 0,65 * R – 49062 * nbParts ergibt.
4.2. Version mit Tabellen (impots_01)
Wir stellen ein erstes Programm vor, bei dem:
- die für die Steuerberechnung erforderlichen Daten in drei Tabellen enthalten sind (Grenzwerte, coeffR, coeffN)
- die Daten der Steuerzahler (verheiratet, Kinder, Gehalt) in einer ersten Textdatei gespeichert sind
- die Ergebnisse der Steuerberechnung (Familienstand, Kinder, Gehalt, Steuer) in einer zweiten Textdatei gespeichert sind
<?php
// Definition der Konstanten
$DATA = "data.txt";
$RESULTATS = "resultats.txt";
$limites = array(12620, 13190, 15640, 24740, 31810, 39970, 48360, 55790, 92970, 127860, 151250, 172040, 195000);
$coeffR = array(0, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65);
$coeffN = array(0, 631, 1290.5, 2072.5, 3309.5, 4900, 6898.5, 9316.5, 12106, 16754.5, 23147.5, 30710, 39312, 49062);
// Daten einlesen
$data = fopen($DATA, "r");
if (!$data) {
print "Impossible d'ouvrir en lecture le fichier des données [$DATA]\n";
exit;
}
// Ergebnisdatei öffnen
$résultats = fopen($RESULTATS, "w");
if (!$résultats) {
print "Impossible de créer le fichier des résultats [$RESULTATS]\n";
exit;
}
// Die aktuelle Zeile der Datendatei wird ausgewertet
while ($ligne = fgets($data, 100)) {
// Eventuelles Zeilenendezeichen wird entfernt
$ligne = cutNewLineChar($ligne);
// Die drei Felder „verheiratet“, „Kinder“ und „Gehalt“ werden abgerufen, die $ligne bilden
list($marié, $enfants, $salaire) = explode(",", $ligne);
// Die Steuer wird berechnet
$impôt = calculImpots($marié, $enfants, $salaire, $limites, $coeffR, $coeffN);
// Das Ergebnis wird in die Ergebnisdatei geschrieben
fputs($résultats, "$marié:$enfants:$salaire:$impôt\n");
// Nächster Steuerzahler
}
// Dateien werden geschlossen
fclose($data);
fclose($résultats);
// Ende
exit;
// --------------------------------------------------------------------------
function cutNewLinechar($ligne) {
// Das Zeilenendezeichen von $ligne wird gelöscht, falls vorhanden
$L = strlen($ligne); // Zeilenzahl
while (substr($ligne, $L - 1, 1) == "\n" or substr($ligne, $L - 1, 1) == "\r") {
$ligne = substr($ligne, 0, $L - 1);
$L--;
}
// Ende
return($ligne);
}
// --------------------------------------------------------------------------
function calculImpots($marié, $enfants, $salaire, $limites, $coeffR, $coeffN) {
// $marié: ja, nein
// $enfants: Anzahl der Kinder
// $salaire: Jahresgehalt
// $limites, $coeffR, $coeffN: Datentabellen zur Berechnung der Steuer
// Anzahl der Anteile
$marié = strtolower($marié);
if ($marié == "oui")
$nbParts = $enfants / 2 + 2;
else
$nbParts=$enfants / 2 + 1;
// ein weiterer 1/2 Anteil, wenn mindestens 3 Kinder vorhanden sind
if ($enfants >= 3)
$nbParts+=0.5;
// steuerpflichtiges Einkommen
$revenuImposable = 0.72 * $salaire;
// Familienquotient
$quotient = $revenuImposable / $nbParts;
// wird am Ende der Tabelle „Grenzwerte“ eingefügt, um die folgende Schleife zu beenden
array_push($limites, $quotient);
// Steuerberechnung
$i = 0;
while ($quotient > $limites[$i])
$i++;
// da $quotient am Ende des Arrays $limites platziert wurde, wird die vorherige Schleife
// darf nicht über das Array $limites hinausgehen
// Nun kann die Steuer berechnet werden
return floor($revenuImposable * $coeffR[$i] - $nbParts * $coeffN[$i]);
}
?>
Die Datendatei data.txt (verheiratet, Kinder, Gehalt):
Die Datei résultats.txt (verheiratet, Kinder, Gehalt, Steuern) mit den erzielten Ergebnissen:
oui:2:200000:22504
non:2:200000:33388
oui:3:200000:16400
non:3:200000:22504
oui:5:50000:0
non:0:3000000:1354938
Anmerkungen
- Zeile 4: Name der Textdatei, die die Daten der Steuerpflichtigen enthält (verheiratet, Kinder, Gehalt)
- Zeile 5: Name der Textdatei, die die Ergebnisse (Familienstand, Kinder, Gehalt, Steuer) der Steuerberechnung enthält
- Zeilen 6–8: die drei Datentabellen, die die Berechnung der Steuer ermöglichen
- Zeilen 11–15: Öffnen der Steuerzahler-Datei im Lesemodus
- Zeilen 18–22: Die Ergebnisdatei wird zum Schreiben geöffnet
- Zeile 25: Schleife zum Einlesen der Zeilen (verheiratet, Kinder, Gehalt) aus der Steuerzahlerdatei
- Zeile 27: Das Zeilenendezeichen wird entfernt
- Zeile 29: Die Bestandteile (verheiratet, Kinder, Gehalt) der Zeile werden abgerufen
- Zeile 31: Die Steuer wird berechnet
- Zeile 33: Die Steuer wird in der Ergebnisdatei gespeichert
- Zeilen 37–38: Sobald die Steuerzahlerdatei vollständig verarbeitet ist, werden die Dateien geschlossen
- Zeile 44: Die Funktion, die das Zeilenendezeichen aus einer Zeile $ligne entfernt. Das Zeilenendezeichen ist die Zeichenkette „\r\n“ auf Windows-Systemen und „\n“ auf Unix-Systemen. Das Ergebnis ist die Eingabezeichenkette ohne ihr Zeilenendezeichen.
- Zeilen 47–48: substr($chaîne,$début,$taille) ist die Teilzeichenfolge von $chaîne, die beim Zeichen $début beginnt und höchstens $taille Zeichen umfasst.
- Zeile 63: strtolower($chaîne) wandelt $chaîne in Kleinbuchstaben um
- Zeile 76: array_push($tableau,$élément) fügt $élément am Ende des Arrays $tableau hinzu. Es ist zu beachten, dass das Array $limites per Wert an die Funktion calculerImpot übergeben wurde (Zeile 56: )). Das Hinzufügen des Elements erfolgt somit an der Kopie des tatsächlichen Parameters, wobei dieser selbst unverändert bleibt.
- Zeile 84: Die Funktion floor($x) liefert den ganzzahligen Wert, der unmittelbar kleiner ist als $x.
4.3. Version mit Textdateien (impots_02)
Diese neue Version unterscheidet sich von der vorherigen lediglich dadurch, dass die für die Steuerberechnung erforderlichen Daten ($limites, $coeffR, $coeffN) nun in einer Textdatei in folgender Form vorliegen:
Datei impots.txt:
12620:13190:15640:24740:31810:39970:48360:55790:92970:127860:151250:172040:195000:0
0:0.05:0.1:0.15:0.2:0.25:0.3:0.35:0.4:0.45:0.5:0.55:0.6:0.65
0:631:1290.5:2072.5:3309.5:4900:6898.5:9316.5:12106:16754.5:23147.5:30710:39312:49062
Die neue Version liest lediglich die Daten aus der Datei [impots.txt] ein, um sie in drei Tabellen ($limites, $coeffR, $coeffN) zu übertragen. Damit sind wir wieder beim vorherigen Fall angelangt. Wir stellen hier nur die Änderungen vor:
<?php
// Definition der Konstanten
$DATA = "data.txt";
$RESULTATS = "resultats.txt";
$IMPOTS = "impots.txt";
// Die für die Steuerberechnung erforderlichen Daten wurden in die Datei $IMPOTS gespeichert
// mit jeweils einer Zeile pro Tabelle in der Form
// val1:val2:val3,...
list($erreur, $limites, $coeffR, $coeffN) = getTables($IMPOTS);
// Ist ein Fehler aufgetreten?
if ($erreur) {
print "$erreur\n";
exit;
}//if
// Lesen der Benutzerdaten
...
// Ende
exit;
// --------------------------------------------------------------------------
function cutNewLinechar($ligne) {
// Das Zeilenendezeichen von $ligne wird entfernt, falls vorhanden
...
}
// --------------------------------------------------------------------------
function calculImpots($marié, $enfants, $salaire, $limites, $coeffR, $coeffN) {
// $marié: ja, nein
// $enfants: Anzahl der Kinder
// $salaire: Jahresgehalt
// $limites, $coeffR, $coeffN: Datentabellen zur Berechnung der Steuer
...
}
// --------------------------------------------------------------------------
function getTables($IMPOTS) {
// $IMPOTS: der Name der Datei, die die Daten der Tabellen $limites, $coeffR und $coeffN enthält
// Existiert die Datei $IMPOTS?
if (!file_exists($IMPOTS))
return array("Le fichier $IMPOTS n'existe pas","","","");
// Blockweises Einlesen der Datei
$tables = file($IMPOTS);
if (!$tables)
return array("Erreur lors de l'exploitation du fichier $IMPOTS","","","");
// Erstellung der 3 Tabellen – es wird davon ausgegangen, dass die Zeilen syntaktisch korrekt sind
$limites = explode(":", cutNewLineChar($tables[0]));
$coeffR = explode(":", cutNewLineChar($tables[1]));
$coeffN = explode(":", cutNewLineChar($tables[2]));
// Ende
return array("", $limites, $coeffR, $coeffN);
}
?>
Anmerkungen
- Zeile 11: Die Funktion getTables($IMPOTS) verarbeitet die Textdatei $IMPOTS, um daraus die drei Tabellen ($limites, $coeffR, $coeffN). Das Ergebnis lautet ($erreur, $limites, $coeffR, $coeffN), wobei $erreur eine Fehlermeldung ist, die leer bleibt, wenn kein Fehler aufgetreten ist.
- Zeile 40: die Funktion getTables($IMPOTS).
- Zeile 43: Die Funktion files_exists(nom_fichier) gibt den Booleschen Wert true zurück, wenn die Datei nom_fichier existiert, andernfalls den Booleschen Wert false.
- Zeile 46: Die Funktion
file(nom\_fichier)liest die gesamte Textdatei *nom\_fichier*. Sie gibt ein Array zurück, in dem jedes Element eine Zeile der Textdatei darstellt. Da die Datei*impots.txt*in diesem Fall drei Textzeilen enthält, gibt die Funktion ein Array mit drei Elementen zurück. - Zeilen 50–52: Verwendung der drei abgerufenen Zeilen zur Erstellung der drei Arrays ($limites, $coeffR, $coeffN)
Die Ergebnisse entsprechen denen der vorherigen Version.