4. Uygulama alıştırması – [IMPOTS]
![]() |
4.1. Sorun
Bir vergi mükellefinin vergisini hesaplayan bir program yazmak istiyoruz. Beyan edeceği tek geliri maaşı olan bir vergi mükellefi durumunu ele alalım:
- Çalışanın pay sayısı şu şekilde hesaplanır: nbParts = nbEnfants/2 + 1 (eğer bekarsa), evliyse nbEnfants/2+2 olarak hesaplanır; burada nbEnfants, çalışanın çocuk sayısıdır;
- vergilendirilebilir geliri R=0,72*S olarak hesaplanır; burada S, yıllık maaşıdır;
- aile katsayısı Q = R/N olarak hesaplanır;
- aşağıdaki verilere göre vergisi I hesaplanır.
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
Her satırda 3 alan vardır. I vergisini hesaplamak için, QF <= alan1 olan ilk satırı ararız. Örneğin, QF = 30000 ise şu satırı buluruz:
Bu durumda I vergisi, 0,15*R - 2072,5*nbParts'e eşittir. Eğer QF, QF<=alan1 ilişkisi hiçbir zaman geçerli olmayacak şekilde belirlenmişse, o zaman son satırdaki katsayılar kullanılır. Burada:
bu da I=0,65*R - 49062*nbParts vergi tutarını verir.
4.2. Listeli sürüm
# -*- coding=utf-8 -*-
import math, sys
def cutNewLineChar(ligne):
# varsa satır sonu işaretini silinir
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):
# evli: evet, hayır
# çocuklar: çocuk sayısı
# maaş: yıllık maaş
# pay sayısı
marie=marie.lower()
if(marie=="oui"):
nbParts=float(enfants)/2+2
else:
nbParts=float(enfants)/2+1
# en az 3 çocuk varsa 1/2 hisse daha
if enfants>=3:
nbParts+=0.5
# vergilendirilebilir gelir
revenuImposable=0.72*salaire
# aile katsayısı
quotient=revenuImposable/nbParts
# takip eden döngüyü durdurmak için sınırlar tablosunun sonuna eklenir
limites[len(limites)-1]=quotient
# vergi hesaplaması
i=0
while(quotient>limites[i]):
i=i+1
# aile katsayısı sınır tablosunun sonuna yerleştirildiği için, önceki döngü
# sınır tablosunun dışına çıkamaz
# artık vergiyi hesaplayabiliriz
return math.floor(revenuImposable*coeffR[i]-nbParts*coeffN[i])
# ------------------------------------------------ ana
# sabitlerin tanımlanması
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]
# verilerin okunması
try:
data=open(DATA,"r")
except:
print "Impossible d'ouvrir en lecture le fichier des donnees [DATA]"
sys.exit()
# sonuç dosyasının açılması
try:
resultats=open(RESULTATS,"w")
except:
print "Impossible de creer le fichier des résultats [RESULTATS]"
sys.exit()
# veri dosyasının geçerli satırını işliyoruz
ligne=data.readline()
while(ligne != ''):
# varsa satır sonu işaretini kaldırma
ligne=cutNewLineChar(ligne)
# satırı oluşturan "evli:çocuk sayısı:maaş" şeklindeki 3 alanı alınır
(marie,enfants,salaire)=ligne.split(",")
enfants=int(enfants)
salaire=int(salaire)
# vergi hesaplanır
impot=calculImpots(marie,enfants,salaire,limites,coeffR,coeffN)
# sonuç yazılır
resultats.write("{0}:{1}:{2}:{3}\n".format(marie,enfants,salaire,impot))
# yeni bir satır okunur
ligne=data.readline()
# dosyalar kapatılır
data.close()
resultats.close()
data.txt veri dosyası:
Elde edilen sonuçlara ait resultats.txt dosyaları:
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. Metin dosyaları içeren sürüm
Önceki örnekte, vergi hesaplaması için gerekli veriler üç listede bulunmuştu. Artık bu veriler bir metin dosyasında aranacaktır:
# -*- coding=utf-8 -*-
import math,sys
# --------------------------------------------------------------------------
def getTables(IMPOTS):
# IMPOTS: sınır tablolarının verilerini içeren dosyanın adı, coeffR, coeffN
# IMPOTS dosyası mevcut mu?
try:
data=open(IMPOTS,"r")
except:
return ("Le fichier IMPOTS n'existe pas",0,0,0)
# 3 listenin oluşturulması - satırların sözdizimsel olarak doğru olduğu varsayılır
# -- 1. satır
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])
# -- satır 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])
# -- satır 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])
# son
return ("",limites,coeffR,coeffN)
# --------------------------------------------------------------------------
def cutNewLineChar(ligne):
# varsa satır sonu işaretini sileriz
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):
# evli: evet, hayır
# çocuk sayısı: çocuk sayısı
# maaş: yıllık maaş
# pay sayısı
marie=marie.lower()
if(marie=="oui"):
nbParts=float(enfants)/2+2
else:
nbParts=float(enfants)/2+1
# en az 3 çocuk varsa 1/2 hisse daha
if enfants>=3:
nbParts+=0.5
# vergilendirilebilir gelir
revenuImposable=0.72*salaire
# aile katsayısı
quotient=revenuImposable/nbParts
# tablonun sonuna eklenir ve takip eden döngüyü durdurur
limites[len(limites)-1]=quotient
# vergi hesaplaması
i=0
while(quotient>limites[i]):
i=i+1
# aile katsayısı sınır tablosunun sonuna yerleştirildiği için, önceki döngü
# sınır tablosunun dışına çıkamaz
# artık vergiyi hesaplayabiliriz
return math.floor(revenuImposable*coeffR[i]-nbParts*coeffN[i])
# ------------------------------------------------ ana
# sabitlerin tanımlanması
DATA="data.txt"
RESULTATS="resultats.txt"
IMPOTS="impots.txt"
# vergi hesaplaması için gerekli veriler IMPOTS dosyasına yerleştirildi
# tablolar için her bir satırda şu biçimde
# val1:val2:val3,...
(erreur,limites,coeffR,coeffN)=getTables(IMPOTS)
# Bir hata mı oluştu?
if(erreur):
print "{0}\n".format(erreur)
sys.exit()
# verilerin okunması
try:
data=open(DATA,"r")
except:
print "Impossible d'ouvrir en lecture le fichier des donnees [DATA]"
sys.exit()
# sonuç dosyasının açılması
try:
resultats=open(RESULTATS,"w")
except:
print "Impossible de creer le fichier des résultats [RESULTATS]"
sys.exit()
# veri dosyasının geçerli satırı işleniyor
ligne=data.readline()
while(ligne != ''):
# varsa satır sonu işaretini kaldırılıyor
ligne=cutNewLineChar(ligne)
# satırı oluşturan "evli:çocuk sayısı:maaş" şeklindeki 3 alanı alınır
(marie,enfants,salaire)=ligne.split(",")
enfants=int(enfants)
salaire=int(salaire)
# vergi hesaplanır
impot=calculImpots(marie,enfants,salaire,limites,coeffR,coeffN)
# sonuç yazılır
resultats.write("{0}:{1}:{2}:{3}\n".format(marie,enfants,salaire,impot))
# yeni bir satır okunur
ligne=data.readline()
# dosyalar kapatılır
data.close()
resultats.close()
Öncekiyle aynı.
Yukarıdaki getImpots yöntemi (satır 6-36), bir tuple döndürür (erreur, limites, coeffR, coeffN) döndürür; burada erreur, boş olabilen bir hata mesajıdır. Bu hata durumlarını istisnalarla yönetmek istenebilir. Bu durumda:
- hata durumunda, getImpots yöntemi bir istisna döndürür;
- aksi takdirde (limites, coeffR, coeffN) tuple'ını döndürür.
Böylece getImpots yönteminin kodu şu şekilde olur:
def getTables(IMPOTS):
# IMPOTS: sınır tablolarının verilerini içeren dosyanın adı, coeffR, coeffN
# IMPOTS dosyası mevcut mu? Değilse, bu durumda IOError istisnası tetiklenir
data=open(IMPOTS,"r")
# 3 listenin oluşturulması - satırların sözdizimsel olarak doğru olduğu varsayılır
# -- satır 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])
# -- satır 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])
# -- satır 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])
# son
return (limites,coeffR,coeffN)
-
- satır: Dosyanın açılmasının başarısız olup olmadığı kontrol edilmez. Başarısız olursa, IOError istisnası atılır. Bu istisna, çağıran programa iletilir;
- 9-10. satırlar: Beklenen ilk satırın bulunmadığını belirtmek için bir istisna atıyoruz. Önceden tanımlanmış RuntimeError istisnasını kullanıyoruz. Kendi istisna sınıflarımızı da oluşturabiliriz. Bunu biraz ileride yapacağız;
- 16-17 ve 23-24. satırlar: 2. ve 3. satırlar için de aynı işlemi tekrarlıyoruz.
Ana programın kodu şu şekilde olur:
# ------------------------------------------------ main
# sabitlerin tanımı
DATA="data.txt"
RESULTATS="resultats.txt"
IMPOTS="impots.txt"
# vergi hesaplaması için gerekli veriler IMPOTS dosyasına yerleştirilmiştir
# tablolar için her bir satırda şu biçimde
# val1:val2:val3,...
erreur=False
try:
(limites,coeffR,coeffN)=getTables(IMPOTS)
except IOError, message:
erreur=True
except RuntimeError, message:
erreur=True
# Bir hata mı oluştu?
if(erreur):
print "L'erreur suivante s'est produite : {0}\n".format(message)
sys.exit()
# verilerin okunması
...
- 12-17. satırlar: getImpots yöntemini çağırıyoruz ve bu yöntemin atabileceği iki istisnayı işliyoruz: IOError ve RuntimeError. Bu işlemde, sadece bir hata oluştuğunu not ediyoruz;
- 20-22. satırlar: Yakalanan istisnanın hata mesajını görüntüler ve programı sonlandırırız.
