4. Anwendungsübung – [IMPOTS]
![]() |
4.1. Die Aufgabe
Es soll ein Programm geschrieben werden, mit dem die Steuer eines Steuerpflichtigen berechnet werden kann. Wir betrachten den vereinfachten Fall eines Steuerpflichtigen, der nur sein Gehalt anzugeben hat:
- Man berechnet die Anzahl der Anteile des Arbeitnehmers 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;
- seine Steuer I wird anhand der folgenden Daten berechnet.
12620.0 0 0
13190 0.05 631
15640 0.1 1290.5
24740 0.15 2072.5
31810 0.2 3309.5
39970 0.25 4900
48360 0.3 6898.5
55790 0.35 9316.5
92970 0.4 12106
127860 0.45 16754.5
151250 0.50 23147.5
172040 0.55 30710
195000 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 folgende Zeile gefunden:
Die Steuer I beträgt dann 0,15*R – 2072,5*nbParts. Wenn QF so gewählt ist, dass die Beziehung QF <= Feld1 niemals erfüllt ist, werden die Koeffizienten der letzten Zeile verwendet. In diesem Fall:
was die Steuer I = 0,65 * R – 49062 * nbParts ergibt.
4.2. Version mit Listen
# -*- coding=utf-8 -*-
import math, sys
def cutNewLineChar(ligne):
# Die Zeilenende-Markierung wird entfernt, falls vorhanden
l=len(ligne);
while(ligne[l-1]=="\n" or ligne[l-1]=="\r"):
l-=1
return(ligne[0:l]);
# --------------------------------------------------------------------------
def calculImpots(marie,enfants,salaire,limites,coeffR,coeffN):
# verheiratet: ja, nein
# Kinder: Anzahl der Kinder
# Gehalt: Jahresgehalt
# Anzahl der Anteile
marie=marie.lower()
if(marie=="oui"):
nbParts=float(enfants)/2+2
else:
nbParts=float(enfants)/2+1
# ein halber Anteil zusätzlich, 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
limites[len(limites)-1]=quotient
# Steuerberechnung
i=0
while(quotient>limites[i]):
i=i+1
# Da der Familienquotient am Ende des Grenzwert-Arrays platziert wurde, wird die vorherige Schleife
# kann nicht über die Grenzen des Grenzwertetabells hinausgehen
# Nun kann die Steuer berechnet werden
return math.floor(revenuImposable*coeffR[i]-nbParts*coeffN[i])
# ------------------------------------------------ Hauptprogramm
# Definition der Konstanten
DATA="data.txt"
RESULTATS="resultats.txt"
limites=[12620,13190,15640,24740,31810,39970,48360,55790,92970,127860,151250,172040,195000,0]
coeffR=[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=[0,631,1290.5,2072.5,3309.5,4900,6898.5,9316.5,12106,16754.5,23147.5,30710,39312,49062]
# Daten einlesen
try:
data=open(DATA,"r")
except:
print "Impossible d'ouvrir en lecture le fichier des donnees [DATA]"
sys.exit()
# Ergebnisdatei öffnen
try:
resultats=open(RESULTATS,"w")
except:
print "Impossible de creer le fichier des résultats [RESULTATS]"
sys.exit()
# Auswertung der aktuellen Zeile der Datendatei
ligne=data.readline()
while(ligne != ''):
# Eventuelles Zeilenendezeichen wird entfernt
ligne=cutNewLineChar(ligne)
# die drei Felder „verheiratet:Kinder:Gehalt“, aus denen die Zeile besteht, werden abgerufen
(marie,enfants,salaire)=ligne.split(",")
enfants=int(enfants)
salaire=int(salaire)
# Die Steuer wird berechnet
impot=calculImpots(marie,enfants,salaire,limites,coeffR,coeffN)
# Das Ergebnis wird eingetragen
resultats.write("{0}:{1}:{2}:{3}\n".format(marie,enfants,salaire,impot))
# eine neue Zeile wird gelesen
ligne=data.readline()
# Die Dateien werden geschlossen
data.close()
resultats.close()
Die Datendatei data.txt:
Die Datei resultats.txt mit den erzielten Ergebnissen:
oui:2:200000:22504.0
non:2:200000:33388.0
oui:3:200000:16400.0
non:3:200000:22504.0
oui:5:50000:0.0
non:0:3000000:1354938.0
4.3. Version mit Textdateien
Im vorherigen Beispiel wurden die für die Steuerberechnung erforderlichen Daten in drei Listen gefunden. Künftig werden sie in einer Textdatei gesucht:
# -*- coding=utf-8 -*-
import math,sys
# --------------------------------------------------------------------------
def getTables(IMPOTS):
# IMPOTS: Name der Datei, die die Daten der Grenztabellen enthält, coeffR, coeffN
# Gibt es die Datei IMPOTS?
try:
data=open(IMPOTS,"r")
except:
return ("Le fichier IMPOTS n'existe pas",0,0,0)
# Erstellung der 3 Listen – es wird davon ausgegangen, dass die Zeilen syntaktisch korrekt sind
# -- Zeile 1
ligne=data.readline()
if ligne== '':
return ("La premiere ligne du fichier {0} est absente".format(IMPOTS),0,0,0)
limites=cutNewLineChar(ligne).split(":")
for i in range(len(limites)):
limites[i]=int(limites[i])
# -- Zeile 2
ligne=data.readline()
if ligne== '':
return ("La deuxieme ligne du fichier {0} est absente".format(IMPOTS),0,0,0)
coeffR=cutNewLineChar(ligne).split(":")
for i in range(len(coeffR)):
coeffR[i]=float(coeffR[i])
# – Zeile 3
ligne=data.readline()
if ligne== '':
return ("La troisieme ligne du fichier {0} est absente".format(IMPOTS),0,0,0)
coeffN=cutNewLineChar(ligne).split(":")
for i in range(len(coeffN)):
coeffN[i]=float(coeffN[i])
# Ende
return ("",limites,coeffR,coeffN)
# --------------------------------------------------------------------------
def cutNewLineChar(ligne):
# Die Zeilenende-Markierung wird entfernt, falls vorhanden
l=len(ligne);
while(ligne[l-1]=="\n" or ligne[l-1]=="\r"):
l-=1
return(ligne[0:l]);
# --------------------------------------------------------------------------
def calculImpots(marie,enfants,salaire,limites,coeffR,coeffN):
# verheiratet: ja, nein
# Kinder: Anzahl der Kinder
# Gehalt: Jahresgehalt
# Anzahl der Anteile
marie=marie.lower()
if(marie=="oui"):
nbParts=float(enfants)/2+2
else:
nbParts=float(enfants)/2+1
# ein halber Anteil zusätzlich, 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
limites[len(limites)-1]=quotient
# Steuerberechnung
i=0
while(quotient>limites[i]):
i=i+1
# Da der Familienquotient am Ende des Grenzwert-Arrays platziert wurde, wird die vorherige Schleife
# kann nicht über die Grenzen des Grenzwertetabells hinausgehen
# Nun kann die Steuer berechnet werden
return math.floor(revenuImposable*coeffR[i]-nbParts*coeffN[i])
# ------------------------------------------------ Hauptprogramm
# Definition der Konstanten
DATA="data.txt"
RESULTATS="resultats.txt"
IMPOTS="impots.txt"
# Die für die Steuerberechnung erforderlichen Daten wurden in die Datei IMPOTS geschrieben
# mit jeweils einer Zeile pro Tabelle in der Form
# val1:val2:val3,...
(erreur,limites,coeffR,coeffN)=getTables(IMPOTS)
# Ist ein Fehler aufgetreten?
if(erreur):
print "{0}\n".format(erreur)
sys.exit()
# Daten werden gelesen
try:
data=open(DATA,"r")
except:
print "Impossible d'ouvrir en lecture le fichier des donnees [DATA]"
sys.exit()
# Ergebnisdatei öffnen
try:
resultats=open(RESULTATS,"w")
except:
print "Impossible de creer le fichier des résultats [RESULTATS]"
sys.exit()
# Die aktuelle Zeile der Datendatei wird verarbeitet
ligne=data.readline()
while(ligne != ''):
# Das eventuelle Zeilenendezeichen wird entfernt
ligne=cutNewLineChar(ligne)
# die drei Felder „verheiratet:Kinder:Gehalt“, aus denen die Zeile besteht, werden abgerufen
(marie,enfants,salaire)=ligne.split(",")
enfants=int(enfants)
salaire=int(salaire)
# Die Steuer wird berechnet
impot=calculImpots(marie,enfants,salaire,limites,coeffR,coeffN)
# Das Ergebnis wird eingetragen
resultats.write("{0}:{1}:{2}:{3}\n".format(marie,enfants,salaire,impot))
# eine neue Zeile wird gelesen
ligne=data.readline()
# Die Dateien werden geschlossen
data.close()
resultats.close()
Die gleichen wie zuvor.
Die oben genannte Methode getImpots (Zeilen 6–36) gibt ein Tupel zurück (erreur, limites, coeffR, coeffN), wobei erreur eine möglicherweise leere Fehlermeldung ist. Man möchte diese Fehlerfälle möglicherweise mit Ausnahmen behandeln. In diesem Fall:
- Im Fehlerfall löst die Methode getImpots eine Ausnahme aus;
- Andernfalls gibt sie das Tupel (limites, coeffR, coeffN) zurück.
Der Code der Methode getImpots sieht dann wie folgt aus:
def getTables(IMPOTS):
# IMPOTS: Name der Datei, die die Daten der Grenztabellen enthält, coeffR, coeffN
# Existiert die Datei IMPOTS? Falls nicht, wird in diesem Fall die Ausnahme IOError ausgelöst
data=open(IMPOTS,"r")
# Erstellung der 3 Listen – es wird davon ausgegangen, dass die Zeilen syntaktisch korrekt sind
# -- Zeile 1
ligne=data.readline()
if ligne== '':
raise RuntimeError ("La premiere ligne du fichier {0} est absente".format(IMPOTS))
limites=cutNewLineChar(ligne).split(":")
for i in range(len(limites)):
limites[i]=int(limites[i])
# – Zeile 2
ligne=data.readline()
if ligne== '':
raise RuntimeError ("La deuxieme ligne du fichier {0} est absente".format(IMPOTS))
coeffR=cutNewLineChar(ligne).split(":")
for i in range(len(coeffR)):
coeffR[i]=float(coeffR[i])
# – Zeile 3
ligne=data.readline()
if ligne== '':
raise RuntimeError ("La troisieme ligne du fichier {0} est absente".format(IMPOTS))
coeffN=cutNewLineChar(ligne).split(":")
for i in range(len(coeffN)):
coeffN[i]=float(coeffN[i])
# Ende
return (limites,coeffR,coeffN)
- Zeile 4: Es wird nicht geprüft, ob das Öffnen der Datei fehlschlägt. Falls dies der Fall ist, wird eine Ausnahme vom Typ IOError ausgelöst. Diese wird an das aufrufende Programm weitergeleitet;
- Zeilen 9–10: Es wird eine Ausnahme ausgelöst, um anzuzeigen, dass die erwartete erste Zeile fehlt. Dabei wird eine vordefinierte Ausnahme RuntimeError verwendet. Man kann auch eigene Ausnahmeklassen erstellen. Dies werden wir etwas später tun;
- Zeilen 16–17 und 23–24: Das Gleiche wird für die Zeilen 2 und 3 wiederholt.
Der Code des Hauptprogramms sieht dann wie folgt aus:
# ------------------------------------------------ main
# Definition der Konstanten
DATA="data.txt"
RESULTATS="resultats.txt"
IMPOTS="impots.txt"
# Die für die Steuerberechnung erforderlichen Daten wurden in die Datei IMPOTS geschrieben
# mit jeweils einer Zeile pro Tabelle in der Form
# val1:val2:val3,...
erreur=False
try:
(limites,coeffR,coeffN)=getTables(IMPOTS)
except IOError, message:
erreur=True
except RuntimeError, message:
erreur=True
# Ist ein Fehler aufgetreten?
if(erreur):
print "L'erreur suivante s'est produite : {0}\n".format(message)
sys.exit()
# Daten werden gelesen
...
- Zeilen 12–17: Wir rufen die Methode getImpots auf und behandeln die beiden Ausnahmen, die sie auslösen kann: IOError und RuntimeError. Bei dieser Behandlung beschränken wir uns darauf, zu vermerken, dass ein Fehler aufgetreten ist;
- Zeilen 20–22: Die Fehlermeldung der abgefangenen Ausnahme wird angezeigt und das Programm wird beendet.
