4. تمرين تطبيقي – [حساب الضرائب]
4.1. المسألة
نهدف إلى كتابة برنامج لحساب ضريبة دافع الضرائب. نأخذ في الاعتبار الحالة المبسطة لدافع الضرائب الذي لا يبلغ سوى عن راتبه:
- نحسب عدد شرائح الضريبة للموظف nbParts = nbChildren / 2 + 1 إذا كان غير متزوج، و nbChildren / 2 + 2 إذا كان متزوجًا، حيث nbChildren هو عدد الأطفال؛
- نحسب دخله الخاضع للضريبة R = 0.72 * S، حيث S هو راتبه السنوي؛
- نحسب معامل الأسرة Q = R/N؛
- نحسب ضريبته I بناءً على البيانات التالية.
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
يحتوي كل صف على 3 حقول. لحساب الضريبة I، ابحث عن الصف الأول الذي يكون فيه QF <= الحقل 1. على سبيل المثال، إذا كان QF = 30,000، فسيكون الصف الذي تم العثور عليه هو:
تكون الضريبة I عندئذٍ مساوية لـ 0.15*R - 2072.5*nbParts. إذا كان QF بحيث لا يتم استيفاء الشرط QF<=field1 أبدًا، يتم استخدام المعاملات من الصف الأخير. هنا:
مما يعطي الضريبة I = 0.65*R - 49062*nbParts.
4.2. الإصدار الذي يستخدم القوائم
البرنامج (impots_01)
| # -*- coding=utf-8 -*-
import math, sys
def cutNewLineChar(ligne):
# delete the end-of-line mark if it exists
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):
# married: yes, no
# children: number of children
# salary: annual salary
# number of shares
marie=marie.lower()
if(marie=="oui"):
nbParts=float(enfants)/2+2
else:
nbParts=float(enfants)/2+1
# an additional 1/2 share if at least 3 children
if enfants>=3:
nbParts+=0.5
# taxable income
revenuImposable=0.72*salaire
# family quotient
quotient=revenuImposable/nbParts
# is set at the end of the limit table to stop the following loop
limites[len(limites)-1]=quotient
# tAX CALCULATION
i=0
while(quotient>limites[i]):
i=i+1
# because we've placed quotient at the end of the limit array, the previous loop
# cannot go beyond the limit table
# now we can calculate the tax
return math.floor(revenuImposable*coeffR[i]-nbParts*coeffN[i])
# ------------------------------------------------ main
# definition of constants
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]
# reading data
try:
data=open(DATA,"r")
except:
print "Impossible d'ouvrir en lecture le fichier des donnees [DATA]"
sys.exit()
# open results file
try:
resultats=open(RESULTATS,"w")
except:
print "Impossible de creer le fichier des résultats [RESULTATS]"
sys.exit()
# use the current line of the data file
ligne=data.readline()
while(ligne != ''):
# remove any end-of-line marker
ligne=cutNewLineChar(ligne)
# we retrieve the 3 fields married:children:salary which form the line
(marie,enfants,salaire)=ligne.split(",")
enfants=int(enfants)
salaire=int(salaire)
# tax calculation
impot=calculImpots(marie,enfants,salaire,limites,coeffR,coeffN)
# enter the result
resultats.write("{0}:{1}:{2}:{3}\n".format(marie,enfants,salaire,impot))
# a new line is read
ligne=data.readline()
# close files
data.close()
resultats.close()
|
النتائج
ملف البيانات data.txt:
oui,2,200000
non,2,200000
oui,3,200000
non,3,200000
oui,5,50000
non,0,3000000
ملف results.txt الذي يحتوي على النتائج:
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. الإصدار مع الملفات النصية
في المثال السابق، كانت البيانات اللازمة لحساب الضريبة موجودة في ثلاث قوائم. من الآن فصاعدًا، سيتم استردادها من ملف نصي:
| 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
|
البرنامج (taxes_02)
| # -*- coding=utf-8 -*-
import math,sys
# --------------------------------------------------------------------------
def getTables(IMPOTS):
# IMPOTS: the name of the file containing data from the limit tables, coeffR, coeffN
# does the IMPOTS file exist?
try:
data=open(IMPOTS,"r")
except:
return ("Le fichier IMPOTS n'existe pas",0,0,0)
# create the 3 lists - assume the lines are syntactically correct
# -- line 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])
# -- line 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])
# -- line 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])
# end
return ("",limites,coeffR,coeffN)
# --------------------------------------------------------------------------
def cutNewLineChar(ligne):
# delete the end-of-line mark if it exists
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):
# married: yes, no
# children: number of children
# salary: annual salary
# number of shares
marie=marie.lower()
if(marie=="oui"):
nbParts=float(enfants)/2+2
else:
nbParts=float(enfants)/2+1
# an additional 1/2 share if at least 3 children
if enfants>=3:
nbParts+=0.5
# taxable income
revenuImposable=0.72*salaire
# family quotient
quotient=revenuImposable/nbParts
# is set at the end of the limit array to stop the loop that follows
limites[len(limites)-1]=quotient
# tAX CALCULATION
i=0
while(quotient>limites[i]):
i=i+1
# because we've placed quotient at the end of the limit array, the previous loop
# cannot exceed the limits of the board
# now we can calculate the tax
return math.floor(revenuImposable*coeffR[i]-nbParts*coeffN[i])
# ------------------------------------------------ main
# definition of constants
DATA="data.txt"
RESULTATS="resultats.txt"
IMPOTS="impots.txt"
# the data required to calculate the tax has been placed in the IMPOTS file
# one line per table in the form
# val1:val2:val3,...
(erreur,limites,coeffR,coeffN)=getTables(IMPOTS)
# was there a mistake?
if(erreur):
print "{0}\n".format(erreur)
sys.exit()
# reading data
try:
data=open(DATA,"r")
except:
print "Impossible d'ouvrir en lecture le fichier des donnees [DATA]"
sys.exit()
# open results file
try:
resultats=open(RESULTATS,"w")
except:
print "Impossible de creer le fichier des résultats [RESULTATS]"
sys.exit()
# use the current line of the data file
ligne=data.readline()
while(ligne != ''):
# remove any end-of-line marker
ligne=cutNewLineChar(ligne)
# we retrieve the 3 fields married:children:salary which form the line
(marie,enfants,salaire)=ligne.split(",")
enfants=int(enfants)
salaire=int(salaire)
# tax calculation
impot=calculImpots(marie,enfants,salaire,limites,coeffR,coeffN)
# enter the result
resultats.write("{0}:{1}:{2}:{3}\n".format(marie,enfants,salaire,impot))
# a new line is read
ligne=data.readline()
# close files
data.close()
resultats.close()
|
النتائج
كما في السابق.
البرنامج (taxes_02b)
تُرجع طريقة getImpots المذكورة أعلاه (الأسطر 6–36) مجموعة (error, limits, coeffR, coeffN)، حيث يمثل error رسالة خطأ قد تكون فارغة. قد ترغب في معالجة حالات الخطأ هذه باستخدام الاستثناءات. وفي هذه الحالة:
- إذا حدث خطأ، فإن طريقة getImpots ترمي استثناءً؛
- وإلا، فإنها تُرجع التوبلة (limits، coeffR، coeffN).
يصبح كود طريقة getImpots كما يلي:
| def getTables(IMPOTS):
# IMPOTS: the name of the file containing data from the limit tables, coeffR, coeffN
# does file IMPOTS exist? if not, exception IOError is thrown in this case
data=open(IMPOTS,"r")
# create the 3 lists - assume the lines are syntactically correct
# -- line 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])
# -- line 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])
# -- line 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])
# end
return (limites,coeffR,coeffN)
|
- السطر 4: لا نتحقق مما إذا كان فتح الملف قد فشل. إذا فشل، يتم إثارة استثناء IOError. نسمح لهذا بالانتشار إلى البرنامج المستدعي؛
- السطران 9–10: نثير استثناءً للإشارة إلى أن السطر الأول المتوقع مفقود. نستخدم استثناء RuntimeError محدد مسبقًا. يمكننا أيضًا إنشاء فئات استثناء خاصة بنا. سنفعل ذلك لاحقًا؛
- السطران 16-17 و23-24: نقوم بنفس الشيء بالنسبة للسطرين 2 و3.
يصبح كود البرنامج الرئيسي كما يلي:
# ------------------------------------------------ main
# définition des constantes
DATA="data.txt"
RESULTATS="resultats.txt"
IMPOTS="impots.txt"
# les données nécessaires au calcul de l'impôt ont été placées dans le fichier IMPOTS
# à raison d'une ligne par tableau sous la forme
# val1:val2:val3,...
erreur=False
try:
(limites,coeffR,coeffN)=getTables(IMPOTS)
except IOError, message:
erreur=True
except RuntimeError, message:
erreur=True
# y-a-t-il eu une erreur ?
if(erreur):
print "L'erreur suivante s'est produite : {0}\n".format(message)
sys.exit()
# lecture des données
...
- الأسطر 12-17: نستدعي طريقة getImpots ونعالج الاستثناءين اللذين قد تثيرهما: IOError و RuntimeError. في هذه المعالجة، نكتفي بالإشارة إلى حدوث خطأ؛
- الأسطر 20–22: نعرض رسالة الخطأ الخاصة بالاستثناء الذي تم اعتراضه وننهي البرنامج.