4. Uygulama alıştırması – 1. ve 2. versiyonlar
4.1. Sorun

Yukarıdaki tablo, beyan edecek tek geliri maaşı olan bir vergi mükellefinin basitleştirilmiş durumunda verginin hesaplanmasına olanak tanır. Not (1)’de belirtildiği gibi, bu şekilde hesaplanan vergi, aşağıdaki üç mekanizma uygulanmadan önceki vergidir:
- yüksek gelirler için geçerli olan aile katsayısı tavanı;
- düşük gelirler için uygulanan vergi indirimi ve muafiyeti;
Böylece vergi hesaplaması aşağıdaki adımları içerir [http://impotsurlerevenu.org/comprendre-le-calcul-de-l-impot/1217-calcul-de-l-impot-2019.php]:

Sadece maaşını beyan edecek bir vergi mükellefinin basitleştirilmiş durumunda, bu mükellefin vergisini hesaplamaya yarayan bir program yazmayı amaçlıyoruz:
4.1.1. Brüt verinin hesaplanması
Brüt vergi şu şekilde hesaplanabilir:
Öncelikle vergi mükellefinin pay sayısı hesaplanır:
- her ebeveyn 1 pay sağlar;
- ilk iki çocuk, her biri 1/2 pay sağlar;
- sonraki çocuklar ise her biri 1 pay sağlar:
Dolayısıyla pay sayısı şöyledir:
- nbParts=1+nbEnfants*0,5+(çocuk sayısı-2)*0,5 eğer çalışan evli değilse;
- evliyse nbParts=2+nbEnfants*0,5+(nbEnfants-2)*0,5;
burada nbEnfants, çalışanın çocuk sayısıdır;
- vergilendirilebilir gelir R=0,9*S olarak hesaplanır; burada S yıllık maaştır;
- aile katsayısı QF = R/nbParts olarak hesaplanır;
- brüt vergi I, aşağıdaki verilere göre hesaplanır (2019):
9964 | 0 | 0 |
27519 | 0,14 | 1394,96 |
73779 | 0,3 | 5798 |
156.244 | 0,41 | 13913,69 |
0 | 0,45 | 20163,45 |
Her satırda 3 alan vardır: champ1, champ2, champ3. I vergisini hesaplamak için, QF <= alan1 olan ilk satırı arar ve bu satırdaki değerleri alırız. Örneğin, evli, iki çocuğu olan ve yıllık maaşı S 50.000 avro olan bir çalışan için:
Vergilendirilebilir gelir: R=0,9*S=45.000
Pay sayısı: nbParts=2+2*0,5=3
Aile katsayısı: QF=45.000/3=15.000
QF<=alan1 olan ilk satır şöyledir:
I vergisi ise 0,14*R – 1394,96*nbParts=[0,14*45000-1394,96*3]=2115'e eşittir. Vergi, bir euro aşağı yuvarlanır.
Eğer ilk satırdan itibaren QF <= champ1 ilişkisi geçerliyse, vergi sıfırdır.
QF değeri, QF<=alan1 koşulunun hiçbir zaman karşılanmayacağı şekilde ise, son satırdaki katsayılar kullanılır. Burada:
bu da brüt vergi I=0,45*R – 20163,45*nbParts sonucunu verir.
4.1.2. Aile katsayısı üst sınırı

Aile katsayısı üst sınırı QF'in geçerli olup olmadığını belirlemek için, çocuklar hariç brüt vergi hesaplaması yeniden yapılır. Yine, iki çocuğu olan ve yıllık maaşı S 50.000 avro olan evli bir çalışan için:
Vergilendirilebilir gelir: R=0,9*S=45.000
Pay sayısı: nbParts=2 (çocuklar artık hesaba katılmıyor)
Aile katsayısı: QF=45000/2=22500
QF<=alan1 olan ilk satır şöyledir:
I vergisi ise 0,14*R – 1394,96*nbParts=[0,14*45000-1394,96*2]=3510'a eşittir.
Çocuklardan kaynaklanan maksimum kazanç: 1551 * 2 = 3102 avro
Asgari vergi: 3510 – 3102 = 408 avro
Daha önce hesaplanan 3 paylı brüt vergi 2115 avro, asgari vergi olan 408 avrodan yüksek olduğundan, bu durumda aile tavanı uygulanmaz.
Genel olarak, brüt vergi (vergi1, vergi2) değerinden daha yüksektir; burada:
- [impôt1]: çocuklarla birlikte hesaplanan brüt vergidir;
- [impôt2]: çocukları dikkate almadan hesaplanan ve çocuklarla ilgili maksimum indirim (burada yarım pay başına 1551 avro) düşülmüş brüt vergidir;
4.1.3. İndirim Hesaplaması

Yine, iki çocuğu olan ve yıllık maaşı S 50.000 avro olan evli çalışan için:
Bir önceki adımda elde edilen brüt vergi (2115), bir çift için 2627 avronun altında (bekar için 1595 avro) olduğundan indirim uygulanır. İndirim, aşağıdaki hesaplama ile elde edilir:
indirim = eşik (çift = 1970 / bekar = 1196) - 0,75 * brüt vergi
indirim = 1970 - 0,75 * 2115 = 383,75, 384 avroya yuvarlanır.
Yeni brüt vergi = 2115 - 384 = 1731 avro
4.1.4. Vergi indiriminin hesaplanması

Belirli bir eşik değerin altında, önceki hesaplamalardan elde edilen brüt vergiden %20 oranında bir indirim yapılır. 2019 yılında eşik değerler şu şekildedir:
- bekar: 21.037 avro;
- çift: 42.074 avro; (yukarıdaki örnekte kullanılan 37.968 rakamı hatalı görünüyor);
Bu eşik, 3.797 * (çocukların sağladığı yarım pay sayısı) tutarında artırılır.
Yine, iki çocuğu olan ve yıllık maaşı S 50.000 avro olan evli bir çalışan için:
- vergilendirilebilir geliri (45.000 avro) eşik değerinden (42.074 + 2 * 3.797) = 49.668 avro daha düşüktür;
- bu nedenle vergisinde %20’lik bir indirim hakkına sahiptir: 1731 * 0,2 = 346,2 avro (347 avroya yuvarlanır);
- vergi mükellefinin brüt vergisi şu şekilde hesaplanır: 1.731 - 347 = 1.384 avro;
4.1.5. Net vergi hesaplaması
Hesaplamamız burada sona eriyor: ödenecek net vergi 1384 avro olacaktır. Gerçekte, vergi mükellefi, özellikle kamu yararına veya genel yarara çalışan kuruluşlara yapılan bağışlar için başka indirimlerden de yararlanabilir.
4.1.6. Yüksek gelirli kişiler
Yukarıdaki örneğimiz, çalışanların çoğunu kapsamaktadır. Ancak yüksek gelirli kişilerde vergi hesaplaması farklıdır.
4.1.6.1. Yıllık gelirler üzerindeki %10’luk indirimin üst sınırı
Çoğu durumda, vergilendirilebilir gelir şu formülle hesaplanır: R=0,9*S; burada S, yıllık maaştır. Buna %10’luk indirim denir. Bu indirim için bir üst sınır vardır. 2019 yılında:
- 12.502 avrodan fazla olamaz;
- 437 avrodan az olamaz;
Evli olmayan, çocuğu olmayan ve yıllık maaşı 200.000 avro olan bir çalışanı ele alalım:
- %10'luk indirim 20.000 avro > 12.502 avrodur. Dolayısıyla 12.502 avroya indirilir;
4.1.6.2. Aile katsayısı üst sınırı
Paragrafta belirtilen aile payı üst sınırının geçerli olduğu bir durumu ele alalım. Üç çocuğu olan ve yıllık geliri 100.000 avro olan bir çifti ele alalım. Hesaplama adımlarını tekrar gözden geçirelim:
- %10’luk indirim, 10.000 avro < 12.502 avro’dur. Dolayısıyla, vergilendirilebilir gelir R, 100.000 - 10.000 = 90.000 avrodur;
- çiftin nbParts değeri 2 + 0,5 × 2 + 1 = 4 paydır;
- bu nedenle aile katsayısı QF = R / nbParts = 90.000 / 4 = 22.500 avrodur;
- çocuklu brüt vergisi I1, I1=0,14*90.000-1.394,96*4= 7.020 avrodur;
- çocuksuz brüt vergisi I2:
- QF=90.000/2=45.000 avro;
- I2=0,3*90000-5798*2=15404 avro;
- aile katsayısı üst sınır kuralına göre, çocuklardan kaynaklanan kazanç (1551*4 yarım pay)=6204 avroyu aşamaz. Oysa burada bu tutar I2-I1=15404-7020= 8384 avrodur, yani 6204 avrodan fazladır;
- bu nedenle brüt vergi, I3 = I2-6204 = 15.404 - 6.204 = 9.200 avro olarak yeniden hesaplanır;
Bu çiftin vergi indirimi veya muafiyeti olmayacak ve nihai vergisi 9200 avro olacaktır.
4.1.7. Resmi rakamlar
Vergi hesaplaması karmaşıktır. Belgenin tamamında, testler aşağıdaki örnekler kullanılarak yapılacaktır. Sonuçlar, vergi idaresinin [https://www3.impots.gouv.fr/simulateur/calcul_impot/2019/simplifie/index.htm] simülatöründen alınmıştır:
Vergi mükellefi | Resmi sonuçlar | Belgedeki algoritmanın sonuçları |
2 çocuğu olan ve yıllık geliri 55555 avro olan çift | Vergi = 2815 avro Vergi oranı = %14 | Vergi = 2.814 avro Vergi oranı = %14 |
2 çocuğu olan ve yıllık geliri 50.000 avro olan çift | Vergi = 1385 avro İndirim = 720 avro İndirim = 0 avro Vergi oranı = %14 | Vergi = 1.384 avro İndirim = 384 avro İndirim = 347 avro Vergi oranı = %14 |
3 çocuğu olan ve yıllık geliri 50.000 avro olan çift | Vergi = 0 avro İndirim = 384 avro İndirim = 346 avro Vergi oranı = %14 | Vergi = 0 avro İndirim = 720 euro İndirim = 0 avro Vergi oranı = %14 |
Bekar, 2 çocuğu olan ve yıllık geliri 100.000 euro olan kişi | Vergi = 19.884 euro İndirim = 0 avro İndirim = 0 euro Vergi oranı = %41 | Vergi = 19.884 avro Ek vergi = 4.480 avro İndirim = 0 euro İndirim = 0 euro Vergi oranı = %41 |
Bekar, 3 çocuğu olan ve yıllık geliri 100.000 avro olan kişi | Vergi = 16.782 avro İndirim = 0 euro İndirim = 0 euro Vergi oranı = %41 | Vergi = 16.782 avro Ek vergi = 7.176 avro İndirim = 0 euro İndirim = 0 euro Vergi oranı = %41 |
3 çocuğu olan ve yıllık geliri 100.000 avro olan çift | Vergi = 9.200 avro İndirim = 0 avro İndirim = 0 avro Vergi oranı = %30 | Vergi = 9.200 avro Ek vergi = 2180 avro İndirim = 0 euro İndirim = 0 euro Vergi oranı = %30 |
5 çocuğu olan ve yıllık geliri 100.000 avro olan çift | Vergi = 4.230 avro İndirim = 0 euro İndirim = 0 euro Vergi oranı = %14 | Vergi = 4.230 avro İndirim = 0 euro İndirim=0 euro Vergi oranı = %14 |
Çocuksuz bekar ve yıllık geliri 100.000 avro olan kişi | Vergi = 22.986 avro İndirim = 0 euro İndirim = 0 euro Vergi oranı = %41 | Vergi = 22.986 avro Ek vergi = 0 avro İndirim = 0 euro İndirim = 0 euro Vergi oranı = %41 |
2 çocuğu olan ve yıllık geliri 30.000 avro olan çift | Vergi = 0 euro İndirim = 0 euro İndirim = 0 euro Vergi oranı = %0 | Vergi = 0 euro İndirim = 0 euro İndirim=0 euro Vergi oranı = %0 |
Çocuksuz bekar ve yıllık geliri 200.000 avro olan kişi | Vergi = 64.211 euro İndirim = 0 euro İndirim = 0 euro Vergi oranı = %45 | Vergi = 64.210 avro Ek vergi = 7498 avro İndirim = 0 euro İndirim = 0 euro Vergi oranı = %45 |
3 çocuğu olan ve yıllık geliri 200.000 avro olan çift | Vergi = 42.843 avro İndirim = 0 euro İndirim = 0 euro Vergi oranı = %41 | Vergi = 42.842 avro Ek vergi = 17.283 avro İndirim = 0 euro İndirim = 0 euro Vergi oranı = %41 |
Yukarıda, yüksek gelirli kişilerin iki nedenden dolayı ek olarak ödedikleri tutara “ek vergi” denir:
- yıllık gelirler üzerindeki %10'luk indirimin üst sınırı;
- aile katsayısının üst sınırı;
Bu gösterge, vergi idaresinin simülatöründe yer almadığı için doğrulanamamıştır.
Belgedeki algoritmanın her seferinde doğru bir vergi tutarı verdiği görülmektedir, ancak 1 avroluk bir hata payı bulunmaktadır. Bu hata payı, yuvarlama işlemlerinden kaynaklanmaktadır. Tüm tutarlar bazen bir üst avroya, bazen de bir alt avroya yuvarlanmaktadır. Resmi kuralları bilmediğim için, belgedeki algoritmadaki tutarlar şu şekilde yuvarlanmıştır:
- indirimler ve indirim tutarları için bir üst euroya;
- ek ücretler ve nihai vergi için bir euro aşağı yuvarlanmıştır;
Bundan sonra, sonuçların geçerliliğini doğrulamak için testler yapılacaktır. Bu testler, önceki tablodaki örnekler kullanılarak, 1 euro’luk kabul edilebilir hata payı ile gerçekleştirilecektir.
4.2. Komut dosyalarının ağaç yapısı

4.3. Sürüm 1
4.3.1. Algoritma
Aşağıda, ilk programımızı sunuyoruz:
- vergi hesaplaması için gerekli veriler, kodda tablolar ve sabitler şeklinde sabit olarak kodlanmıştır;
- vergi mükelleflerine ait veriler (evli olup olmadığı, çocuk sayısı, maaş) ilk metin dosyası [taxpayersdata.txt]'te yer almaktadır;
- vergi hesaplamasının sonuçları (evli, çocuk sayısı, maaş, vergi) ikinci bir metin dosyası olan [resultats.txt]'te saklanmaktadır;
[version-01/main.php] komut dosyası şu şekildedir:
<?php
// fonksiyon parametreleri için katı tipler
declare(strict_types=1);
// global sabitler
define("PLAFOND_QF_DEMI_PART", 1551);
define("PLAFOND_REVENUS_CELIBATAIRE_POUR_REDUCTION", 21037);
define("PLAFOND_REVENUS_COUPLE_POUR_REDUCTION", 42074);
define("VALEUR_REDUC_DEMI_PART", 3797);
define("PLAFOND_DECOTE_CELIBATAIRE", 1196);
define("PLAFOND_DECOTE_COUPLE", 1970);
define("PLAFOND_IMPOT_COUPLE_POUR_DECOTE", 2627);
define("PLAFOND_IMPOT_CELIBATAIRE_POUR_DECOTE", 1595);
define("ABATTEMENT_DIXPOURCENT_MAX", 12502);
define("ABATTEMENT_DIXPOURCENT_MIN", 437);
// yerel sabitlerin tanımlanması
$DATA = "taxpayersdata.txt";
$RESULTATS = "resultats.txt";
$limites = array(9964, 27519, 73779, 156244, 0);
$coeffR = array(0, 0.14, 0.3, 0.41, 0.45);
$coeffN = array(0, 1394.96, 5798, 13913.69, 20163.45);
// verilerin okunması
$data = fopen($DATA, "r");
if (!$data) {
print "Impossible d'ouvrir en lecture le fichier des données [$DATA]\n";
exit;
}
// sonuç dosyasının açılması
$résultats = fopen($RESULTATS, "w");
if (!$résultats) {
print "Impossible de créer le fichier des résultats [$RESULTATS]\n";
exit;
}
// veri dosyasının geçerli satırını işleme
while ($ligne = fgets($data, 100)) {
// varsa satır sonu işaretini kaldırma
$ligne = cutNewLineChar($ligne);
// $ligne'i oluşturan "evli:çocuk sayısı:maaş" şeklindeki 3 alanı alınır
list($marié, $enfants, $salaire) = explode(",", $ligne);
// vergi hesaplanır
$result = calculImpot($marié, (int) $enfants, (float) $salaire, $limites, $coeffR, $coeffN);
// sonuç, sonuç dosyasına kaydedilir
$result = ["marié" => $marié, "enfants" => $enfants, "salaire" => $salaire] + $result;
fputs($résultats, \json_encode($result, JSON_UNESCAPED_UNICODE) . "\n");
// sonraki veri
}
// dosyalar kapatılır
fclose($data);
fclose($résultats);
// son
exit;
// --------------------------------------------------------------------------
function cutNewLinechar(string $ligne): string {
// varsa, $ligne dosyasındaki satır sonu işaretini silin
$L = strlen($ligne); // satır uzunluğu
while (substr($ligne, $L - 1, 1) === "\n" or substr($ligne, $L - 1, 1) === "\r") {
$ligne = substr($ligne, 0, $L - 1);
$L--;
}
// son
return($ligne);
}
// vergi hesaplaması
// --------------------------------------------------------------------------
function calculImpot(string $marié, int $enfants, float $salaire, array $limites, array $coeffR, array $coeffN): array {
…
// sonuç
return ["impôt" => floor($impot), "surcôte" => $surcôte, "décôte" => $décôte, "réduction" => $réduction, "taux" => $taux];
}
// --------------------------------------------------------------------------
function calculImpot2(string $marié, int $enfants, float $salaire, array $limites, array $coeffR, array $coeffN): array {
…
// sonuç
return ["impôt" => $impôt, "surcôte" => $surcôte, "taux" => $coeffR[$i]];
}
// revenuImposable=yıllık maaş-muafiyet
// muafiyetin bir minimum ve bir maksimum değeri vardır
function getRevenuImposable(float $salaire): float {
…
// sonuç
return floor($revenuImposable);
}
// olası bir indirimi hesaplar
function getDecote(string $marié, float $salaire, float $impots): float {
…
// sonuç
return ceil($décôte);
}
// olası bir indirimi hesaplar
function getRéduction(string $marié, float $salaire, int $enfants, float $impots): float {
/…
// sonuç
return ceil($réduction);
}
taxpayersdata.txt veri dosyası (evli, çocuk sayısı, maaş):
Elde edilen sonuçlara ait résultats.txt dosyası (evli, çocuk sayısı, maaş, vergi, ek vergi, indirim, vergi indirimi, vergi oranı):
Yorumlar
- 4. satır: fonksiyon parametrelerinin türlerine sıkı bir şekilde uyulması zorunlu kılınır;
- 7-16. satırlar: vergi hesaplaması için gerekli tüm sabitlerin tanımı;
- 19. satır: vergi mükelleflerinin verilerini (evli, çocuk sayısı, maaş) içeren metin dosyasının adı;
- 20. satır: vergi hesaplamasının sonuçlarını (evli, çocuk sayısı, maaş, vergi) içeren metin dosyasının adı;
- 21-23. satırlar: vergi hesaplamasındaki farklı vergi dilimlerini tanımlayan üç veri tablosu;
- satır 26-30: vergi mükellefi veri dosyasının [r] ile okuma modunda açılması. Açma işlemi gerçekleştirilemediğinde [fopen] işlevi, FALSE boole değerini döndürür;
- satır 33-37: sonuç dosyasının [w] ile yazma modunda açılması;
- satır 40-51: vergi mükellefi veri dosyasındaki satırların (eş, çocuklar, maaş) okunması döngüsü;
- satır 40: [fgets] işlevi 100 karakter okur ve karşılaştığı ilk satır sonu işaretinde durur. Burada tüm satırlar 100 karakterden kısadır. Bir satır sonu işareti ile karşılaşılırsa, bu işaret döndürülen dizeye dahil edilir. Dosyanın sonuna ulaşıldığında, [fgets] işlevi FALSE değerini döndürür;
- 42. satır: satır sonu işareti kaldırılır;
- satır 44: satırın bileşenleri (eş, çocuklar, maaş) alınır;
- satır 46: vergi hesaplanır. Sonuç, bir ilişkisel tablo biçiminde döndürülür (satır 76);
- satır 48: daha önce alınan tabloya [marié, enfants, salaire] anahtarları eklenir;
- satır 49: sonuç, sonuç dosyasında jSON dizesi biçiminde kaydedilir;
- satır 53-54: vergi mükellefi veri dosyası tamamen işlendikten sonra dosyalar kapatılır;
- 60. satır: $ligne satırındaki satır sonu işaretini kaldıran işlev. Satır sonu işareti, Windows sistemlerinde "\r\n", Unix sistemlerinde "\n" dizesidir. Sonuç, satır sonu işareti çıkarılmış giriş dizesidir.
- 63-64. satırlar: substr($chaîne,$début,$taille), $chaîne dizesinin $début karakterinden başlayıp en fazla $taille karakter içeren alt dizesidir;
[calculImpot] işlevi şöyledir:
// genel sabitler
define("PLAFOND_QF_DEMI_PART", 1551);
// vergi hesaplaması
// --------------------------------------------------------------------------
function calculImpot(string $marié, int $enfants, float $salaire, array $limites, array $coeffR, array $coeffN): array {
// $marié: evet, hayır
// $enfants: çocuk sayısı
// $salaire: yıllık maaş
// $limites, $coeffR, $coeffN: vergi hesaplamasına olanak tanıyan veri tabloları
//
// çocuklu vergi hesaplaması
$result1 = calculImpot2($marié, $enfants, $salaire, $limites, $coeffR, $coeffN);
$impot1 = $result1["impôt"];
// çocuklar hariç vergi hesaplaması
if ($enfants != 0) {
$result2 = calculImpot2($marié, 0, $salaire, $limites, $coeffR, $coeffN);
$impot2 = $result2["impôt"];
// aile katsayısı tavanının uygulanması
if ($enfants < 3) {
// $PLAFOND_QF_DEMI_PART euro (ilk 2 çocuk için)
$impot2 = $impot2 - $enfants * PLAFOND_QF_DEMI_PART;
} else {
// $PLAFOND_QF_DEMI_PART avro ilk 2 çocuk için, sonraki çocuklar için iki katı
$impot2 = $impot2 - 2 * PLAFOND_QF_DEMI_PART - ($enfants - 2) * 2 * PLAFOND_QF_DEMI_PART;
}
} else {
$impot2 = $impot1;
$result2 = $result1;
}
// ilgili vergi oranı ve ek vergiyle birlikte en yüksek vergi tutarı alınır
if ($impot1 > $impot2) {
$impot = $impot1;
$taux = $result1["taux"];
$surcôte = $result1["surcôte"];
} else {
$surcôte = $impot2 - $impot1 + $result2["surcôte"];
$impot = $impot2;
$taux = $result2["taux"];
}
// Olası bir indirimin hesaplanması
$décôte = getDecote($marié, $salaire, $impot);
$impot -= $décôte;
// olası vergi indiriminin hesaplanması
$réduction = getRéduction($marié, $salaire, $enfants, $impot);
$impot -= $réduction;
// sonuç
return ["impôt" => floor($impot), "surcôte" => $surcôte, "décôte" => $décôte, "réduction" => $réduction, "taux" => $taux];
}
// --------------------------------------------------------------------------
function calculImpot2(string $marié, int $enfants, float $salaire, array $limites, array $coeffR, array $coeffN): array {
…
// sonuç
return ["impôt" => $impôt, "surcôte" => $surcôte, "taux" => $coeffR[$i]];
}
// revenuImposable=yıllıkMaaş-muafiyet
// %10'luk indirim için minimum ve maksimum değerler vardır
function getRevenuImposable(float $salaire): float {
…
}
// olası bir indirimi hesaplar
function getDecote(string $marié, float $salaire, float $impots): float {
…
// sonuç
return ceil($décôte);
}
// olası bir indirimi hesaplar
function getRéduction(string $marié, float $salaire, int $enfants, float $impots): float {
…
// sonuç
return ceil($réduction);
}
Açıklamalar
- 10. satır: Brüt vergi, çocuklarla birlikte hesaplanır. Sonuç, ["impôt" => $impôt, "surcôte" => $surcôte, "taux" => $coeffR[$i]] şeklinde elde edilir; burada:
- [‘impôt’]: brüt vergi;
- [‘surcôte’]: varsa ek vergi tutarı. Bu ek vergi, %10'luk indirim tutarının 12.502 avro eşiğini aştığı durumlarda uygulanır;
- [‘taux’]: vergi mükellefinin vergi oranı;
- 11. satır: ödenecek brüt vergi [impot1];
- 13-14. satırlar: Vergi mükellefinin en az bir çocuğu varsa, vergi hesaplaması aynı veriler kullanılarak ancak çocuk sayısı 0 olarak yeniden yapılır. Bu ikinci hesaplama, çocuklardan kaynaklanan indirimin (nbParts*coeffN) belirli bir eşiği aşıp aşmadığını görmek için gereklidir;
- satır 15: ödenecek brüt vergi [impot2];
- 16-23. satırlar: [impot2] brüt vergisi için artık çocukların etkisi hesaba katılır: Çocukların sağladığı her 1/2 pay, [PLAFOND_QF_DEMI_PART] avro tutarında bir indirim sağlar;
- 25-26. satırlar: Vergi mükellefinin çocuğu olmadığı durumlar. Bu durumda, [impot2]’in hesaplanması gereksizdir. Bu tutar, [impot1]’e eşittir;
- 29-37. satırlar: [impot1, impot2] olmak üzere iki brüt vergi hesaplanmıştır. Vergi dairesi, bu ikisinden daha yüksek olanını esas alır. Sonuç olarak [impot] tutarında bir brüt vergi elde edilir;
- satır 39-40: [impot] brüt tutarı bir indirime tabi tutulabilir;
- satır 42-43: [impot] brüt tutarı bir indirime tabi tutulabilir;
- satır 45: [impot] artık ödenecek net vergidir. Sonuçlar verilir;
[calculImpot2] fonksiyonu şu şekildedir:
// --------------------------------------------------------------------------
function calculImpot2(string $marié, int $enfants, float $salaire, array $limites, array $coeffR, array $coeffN): array {
// $marié: evet, hayır
// $enfants : çocuk sayısı
// $salaire : yıllık maaş
// $limites, $coeffR, $coeffN: vergi hesaplamasına olanak tanıyan veri tabloları
//
// pay sayısı
$marié = strtolower($marié);
if ($marié === "oui") {
$nbParts = $enfants / 2 + 2;
} else {
$nbParts = $enfants / 2 + 1;
}
// 3. çocuktan itibaren her çocuk için 1 pay
if ($enfants >= 3) {
// 3. çocuktan itibaren her çocuk için yarım pay daha
$nbParts += 0.5 * ($enfants - 2);
}
// vergilendirilebilir gelir
$revenuImposable = getRevenuImposable($salaire);
// ek ücret
$surcôte = floor($revenuImposable - 0.9 * $salaire);
// yuvarlama sorunları için
if ($surcôte < 0) {
$surcôte = 0;
}
// aile geliri katsayısı
$quotient = $revenuImposable / $nbParts;
// tablo sınırlarının sonuna eklenir ve ardından gelen döngüyü durdurur
$limites[count($limites) - 1] = $quotient;
// vergi hesaplaması
$i = 0;
while ($quotient > $limites[$i]) {
$i++;
}
// $quotient'in $limites tablosunun sonuna yerleştirilmesi nedeniyle, önceki döngü
// $limites tablosunun sınırlarını aşamaz
// şimdi vergiyi hesaplayabiliriz
$impôt = floor($revenuImposable * $coeffR[$i] - $nbParts * $coeffN[$i]);
// sonuç
return ["impôt" => $impôt, "surcôte" => $surcôte, "taux" => $coeffR[$i]];
}
// revenuImposable=yıllıkMaaş-muafiyet
// muafiyetin bir alt ve üst sınırı vardır
function getRevenuImposable(float $salaire): float {
// sonuç
return floor($revenuImposable);
}
Açıklamalar
- Burada, kademeli vergi tablosuna göre vergi hesaplaması uygulanır;
- 9. satır: strtolower($chaîne) işlevi, $chaîne değerini küçük harflerle döndürür;
- 10-19. satırlar: vergi mükellefinin pay sayısının hesaplanması;
- 21. satır: Bir fonksiyon yardımıyla vergilendirilebilir gelir hesaplanır. Nitekim, bunun her zaman 0,9*revenusAnnuels olmadığını gördük. %10'luk indirim aslında 12.502 avro ile sınırlıdır;
- satır 23: vergilendirilebilir gelir 0,9*revenusAnnuels'ten yüksekse, olası ek verginin hesaplanması;
- 25-27. satırlar: Yuvarlama hataları nedeniyle bazen [$surcôte=-1] değerinin ortaya çıkması durumunu düzeltir;
- 29. satır: aile katsayısı;
- satır 30-36: bu katsayı, vergi mükellefinin vergi dilimini belirlemeye olanak tanır;
- satır 40: vergi mükellefinin vergi dilimi belirlendikten sonra, brüt vergisi hesaplanabilir. floor($x) fonksiyonu, [$x] değerinden hemen küçük olan tamsayı değerini verir;
- satır 42: hesaplanan bilgiler verilir;
[getRevenuImposable] işlevi şu şekildedir:
// genel sabitler
define("ABATTEMENT_DIXPOURCENT_MAX", 12502);
define("ABATTEMENT_DIXPOURCENT_MIN", 437);
// revenuImposable=yıllıkMaaş-indirim
// indirim için minimum ve maksimum değerler vardır
function getRevenuImposable(float $salaire): float {
// maaşın %10'u kadar indirim
$abattement = 0.1 * $salaire;
// Bu indirim, ABATTEMENT_DIXPOURCENT_MAX değerini aşamaz
if ($abattement > ABATTEMENT_DIXPOURCENT_MAX) {
$abattement = ABATTEMENT_DIXPOURCENT_MAX;
}
// indirim, ABATTEMENT_DIXPOURCENT_MIN değerinden daha düşük olamaz
if ($abattement < ABATTEMENT_DIXPOURCENT_MIN) {
$abattement = ABATTEMENT_DIXPOURCENT_MIN;
}
// vergilendirilebilir gelir
$revenuImposable = $salaire - $abattement;
// net kar
return floor($revenuImposable);
}
Açıklamalar
- 5. satır: normal indirim, yıllık maaşın %10'udur;
- 7-9. satırlar: İndirim, [ABATTEMENT_DIXPOURCENT_MAX] numaralı azami indirimi aşamaz;
- satır 10-13: İndirim, asgari indirim tutarından ([ABATTEMENT_DIXPOURCENT_MIN]) daha az olamaz;
- satır 15: vergilendirilebilir gelirin hesaplanması;
[getDecote] fonksiyonu şu şekildedir:
// genel sabitler
define("PLAFOND_DECOTE_CELIBATAIRE", 1196);
define("PLAFOND_DECOTE_COUPLE", 1970);
define("PLAFOND_IMPOT_COUPLE_POUR_DECOTE", 2627);
define("PLAFOND_IMPOT_CELIBATAIRE_POUR_DECOTE", 1595);
// olası bir iskontoyu hesaplar
function getDecote(string $marié, float $salaire, float $impots): float {
// başlangıçta indirim sıfırdır
$décôte = 0;
// indirimden yararlanmak için maksimum vergi tutarı
$plafondImpôtPourDécôte = $marié === "oui" ? PLAFOND_IMPOT_COUPLE_POUR_DECOTE : PLAFOND_IMPOT_CELIBATAIRE_POUR_DECOTE;
if ($impots < $plafondImpôtPourDécôte) {
// indirim tutarının üst sınırı
$plafondDécôte = $marié === "oui" ? PLAFOND_DECOTE_COUPLE : PLAFOND_DECOTE_CELIBATAIRE;
// teorik indirim
$décôte = $plafondDécôte - 0.75 * $impots;
// indirim, vergi tutarını aşamaz
if ($décôte > $impots) {
$décôte = $impots;
}
// <0 indirim uygulanmaz
if ($décôte < 0) {
$décôte = 0;
}
}
// sonuç
return ceil($décôte);
}
Açıklamalar
- 6. satır: İndirimden yararlanabilmek için brüt verginin üst sınırı. Bu tutar, bekarlar ve çiftler için farklıdır;
- 7. satır: Vergi mükellefinin indirim hakkına sahip olup olmadığı;
- 11. satır: indirim formülü. [plafondDécôte], indirimin azami tutarıdır. Bu azami tutar 9. satırda hesaplanır. Burada da vergi mükellefinin evli veya bekar olmasına bağlı olarak değişir;
- 13-15. satırlar: İndirim, ödenecek brüt vergiden fazla olamaz. Örneğin, 11. satırda [impots] değeri 0 ise bu durum söz konusudur;
- 17-19. satırlar: -1'e yuvarlanmasını önlemek için;
[getRéduction] fonksiyonu şu şekildedir:
// genel sabitler
define("PLAFOND_REVENUS_CELIBATAIRE_POUR_REDUCTION", 21037);
define("PLAFOND_REVENUS_COUPLE_POUR_REDUCTION", 42074);
define("VALEUR_REDUC_DEMI_PART", 3797);
// olası bir indirimi hesaplar
function getRéduction(string $marié, float $salaire, int $enfants, float $impots): float {
// %20 indirimden yararlanabilmek için gelir üst sınırı
$plafondRevenuPourRéduction = $marié === "oui" ? PLAFOND_REVENUS_COUPLE_POUR_REDUCTION : PLAFOND_REVENUS_CELIBATAIRE_POUR_REDUCTION;
$plafondRevenuPourRéduction += $enfants * VALEUR_REDUC_DEMI_PART;
if ($enfants > 2) {
$plafondRevenuPourRéduction += ($enfants - 2) * VALEUR_REDUC_DEMI_PART;
}
// vergilendirilebilir gelir
$revenuImposable = getRevenuImposable($salaire);
// indirim
$réduction = 0;
if ($revenuImposable < $plafondRevenuPourRéduction) {
// %20 indirim
$réduction = 0.2 * $impots;
}
// sonuç
return ceil($réduction);
}
Açıklamalar
- 4-10. satırlar: vergi indirimi hakkından yararlanabilmek için, vergilendirilebilir gelirin (10. satır) 4-8. satırlarda hesaplanan üst sınırın altında olması gerekir;
- 13-16. satırlar: Koşulları karşılayan vergi mükellefi, %20 oranında vergi indirimi hakkına sahiptir (15. satır);
4.3.2. Sonuçlar
taxpayersdata.txt veri dosyası (evli, çocuk sayısı, maaş):
résultats.txt dosyası (evli, çocuk sayısı, maaş, vergi, ek vergi, vergi indirimi, indirim, vergi oranı) elde edilen sonuçlar:
Elde edilen sonuçlar, vergi dairesinin simülatörüyle elde edilen sonuçlarla uyumludur.
4.3.3. Sonuç
Vergi hesaplama algoritması, basit olarak kabul edilen durumlarda bile karmaşıktır. Bu konuya bir daha değinmeyeceğiz. Sürümler ilerledikçe, bazı sunum değişikliklerine rağmen algoritmanın özü aynı kalacaktır. Dolayısıyla sadece bu değişiklikler üzerinde durulacaktır.
4.4. Sürüm 2
4.4.1. Değişiklikler
Önceki sürümde, vergi hesaplaması için gerekli veriler sabit değerler ve tablolar şeklinde kodlanmıştı. Bu yöntem kesinlikle kullanılmamalıdır. Yeni sürümde, bu veriler jSON adlı bir dosyaya taşınmıştır:

[taxadmindata.json] dosyasının içeriği şöyledir:
{
"limites": [9964, 27519, 73779, 156244, 0],
"coeffR": [0, 0.14, 0.3, 0.41, 0.45],
"coeffN": [0, 1394.96, 5798, 13913.69, 20163.45],
"PLAFOND_QF_DEMI_PART": 1551,
"PLAFOND_REVENUS_CELIBATAIRE_POUR_REDUCTION": 21037,
"PLAFOND_REVENUS_COUPLE_POUR_REDUCTION": 42074,
"VALEUR_REDUC_DEMI_PART": 3797,
"PLAFOND_DECOTE_CELIBATAIRE": 1196,
"PLAFOND_DECOTE_COUPLE": 1970,
"PLAFOND_IMPOT_COUPLE_POUR_DECOTE": 2627,
"PLAFOND_IMPOT_CELIBATAIRE_POUR_DECOTE": 1595,
"ABATTEMENT_DIXPOURCENT_MAX": 12502,
"ABATTEMENT_DIXPOURCENT_MIN": 437
}
Yeni sürüm [version-02/main.php] şu şekildedir:
<?php
// fonksiyon parametrelerinin beyan edilen türlerine sıkı sıkıya uyulması
declare (strict_types=1);
// sabitlerin tanımlanması
$TAXPAYERSDATA = "taxpayersdata.txt";
$RESULTATS = "resultats.txt";
$TAXADMINDATA = "taxadmindata.json";
// vergi verileri dosyasının içeriği alınır
$fileContents = \file_get_contents($TAXADMINDATA);
$erreur = FALSE;
// hata mı?
if (!$fileContents) {
// hatkın not alınması
$erreur = TRUE;
$message = "Le fichier des données [$TAXADMINDATA] n'existe pas";
}
if (!$erreur) {
// yapılandırma dosyasından jSON kodunu bir ilişkisel diziye alınır
$taxAdminData = \json_decode($fileContents, true);
// hata mı?
if (!$taxAdminData) {
// hata kaydediliyor
$erreur = TRUE;
$message = "Le fichier de données jSON [$TAXADMINDATA] n'a pu être exploité correctement";
}
}
// hata mı?
if ($erreur) {
print "$message\n";
exit;
}
// sonuç dosyasını açıyoruz
$résultats = fopen($RESULTATS, "w");
if (!$résultats) {
print "Impossible de créer le fichier des résultats [$RESULTATS]\n";
// çıkış
exit;
}
// vergi mükellefi verileri dosyasının açılması
$taxpayersdata = fopen($TAXPAYERSDATA, "r");
if (!$taxpayersdata) {
print "Impossible d'ouvrir le fichier des contribuables [$TAXPAYERSDATA]\n";
// çıkış
exit;
}
// veri dosyasının geçerli satırını işliyoruz
while ($ligne = fgets($taxpayersdata, 100)) {
// varsa satır sonu işaretini kaldırma
$ligne = cutNewLineChar($ligne);
// $ligne'i oluşturan "evli:çocuk sayısı:maaş" şeklindeki 3 alanı alınır
list($marié, $enfants, $salaire) = explode(",", $ligne);
// vergi hesaplanır
$result = calculImpot($taxAdminData, $marié, (int) $enfants, (int) $salaire);
// sonuç, sonuç dosyasına kaydedilir
$result = ["marié" => $marié, "enfants" => $enfants, "salaire" => $salaire] + $result;
fputs($résultats, \json_encode($result, JSON_UNESCAPED_UNICODE) . "\n");
// sonraki veri
}
// dosyalar kapatılır
fclose($taxpayersdata);
fclose($résultats);
// son
exit;
// --------------------------------------------------------------------------
function cutNewLinechar(string $ligne) {
…
// son
return($ligne);
}
// vergi hesaplaması
// --------------------------------------------------------------------------
function calculImpot(array $taxAdminData, string $marié, int $enfants, float $salaire) {
// $marié: evet, hayır
// $enfants: çocuk sayısı
// $salaire: yıllık maaş
// $taxAdminData: vergi dairesi verileri
//
// çocuklu vergi hesaplaması
$result1 = calculImpot2($taxAdminData, $marié, $enfants, $salaire);
$impot1 = $result1["impôt"];
// çocuklar hariç vergi hesaplaması
if ($enfants != 0) {
$result2 = calculImpot2($taxAdminData, $marié, 0, $salaire);
$impot2 = $result2["impôt"];
// aile katsayısı üst sınırının uygulanması
if ($enfants < 3) {
// $PLAFOND_QF_DEMI_PART euro (ilk 2 çocuk için)
$impot2 = $impot2 - $enfants * $taxAdminData["PLAFOND_QF_DEMI_PART"];
} else {
// $PLAFOND_QF_DEMI_PART avro ilk 2 çocuk için, sonraki çocuklar için iki katı
$impot2 = $impot2 - 2 * $taxAdminData["PLAFOND_QF_DEMI_PART"] - ($enfants - 2) * 2 * $taxAdminData["PLAFOND_QF_DEMI_PART"];
}
} else {
$impot2 = $impot1;
$result2 = $result1;
}
// ilgili vergi oranı ve ek vergiyle birlikte en yüksek vergi tutarı alınır
if ($impot1 > $impot2) {
$impot = $impot1;
$taux = $result1["taux"];
$surcôte = $result1["surcôte"];
} else {
$surcôte = $impot2 - $impot1 + $result2["surcôte"];
$impot = $impot2;
$taux = $result2["taux"];
}
// Olası bir indirimin hesaplanması
$décôte = getDecote($taxAdminData, $marié, $salaire, $impot);
$impot -= $décôte;
// olası vergi indiriminin hesaplanması
$réduction = getRéduction($taxAdminData, $marié, $salaire, $enfants, $impot);
$impot -= $réduction;
// sonuç
return ["impôt" => floor($impot), "surcôte" => $surcôte, "décôte" => $décôte, "réduction" => $réduction, "taux" => $taux];
}
// --------------------------------------------------------------------------
function calculImpot2(array $taxAdminData, string $marié, int $enfants, float $salaire) {
// $marié: evet, hayır
…
// sonuç
return ["impôt" => $impôt, "surcôte" => $surcôte, "taux" => $coeffR[$i]];
}
// revenuImposable=yıllıkMaaş-muafiyet
// muafiyetin bir minimum ve bir maksimum değeri vardır
function getRevenuImposable(array $taxAdminData, float $salaire): float {
…
// sonuç
return floor($revenuImposable);
}
// olası bir indirimi hesaplar
function getDecote(array $taxAdminData, string $marié, float $salaire, float $impots): float {
…
// sonuç
return ceil($décôte);
}
// olası bir indirimi hesaplar
function getRéduction(array $taxAdminData, string $marié, float $salaire, int $enfants, float $impots): float {
…
// sonuç
return ceil($réduction);
}
Yorumlar
- 11-19. satırlar: jSON adlı dosyanın içeriğini [TAXADMINDATA] olarak okumaya çalışılır;
- 21-30. satırlar: jSON dosyasını okumayı başardıysak, içeriği [$taxAdminData] ilişkisel dizisine kod çözülür;
- satır 32-36: Önceki iki işlemden birinde hata ile karşılaşılırsa, konsola bir hata mesajı yazılır ve program durdurulur;
- 01 sürümüyle arasındaki fark, burada vergi idaresine ait verilerin (diziler ve sabitler) [$taxAdminData] ilişkisel dizisinde yer almasıdır; oysa 01 sürümünde bunlar küresel diziler ve sabitler içindeydi. İki sürüm arasındaki farkı oluşturan, işte bu sabitlerin küresel olmasıdır:
- 01 sürümünde, sabitler [main.php] tablosundaki tüm işlevlerde biliniyordu;
- sürüm 02’de aynı sonuca ulaşmak için, [$taxAdminData] ilişkisel tablosunu tüm fonksiyonlara parametre olarak aktarmak gerekir (satır 83, 129, 138, 145, 152);
- sürüm 02'deki her fonksiyon, [$taxAdminData] tablosunun içeriğini kullanmalıdır;
- 83-126. satırlar: [calculerImpot] fonksiyonunda, daha önce global sabitler veya [limites, coeffR, coeffN] tabloları kullanıldığı yerlerde, artık parametre olarak alınan [$taxAdminData] tablosunun içeriği kullanılmaktadır (satır 99, 102);
- diğer tüm fonksiyonlar da aynı şekilde yeniden yazılmıştır;
Elde edilen sonuçlar, önceki sürümde elde edilenlerle aynıdır.
4.4.2. Sonuç
02 sürümü, 01 sürümünden çok daha esnektir. 2020 yılında, vergi hesaplama algoritması muhtemelen 2019’dakiyle aynı olacaktır. Yalnızca vergi dilimleri ve hesaplama sabitleri değişecektir. Bu durumda [taxadmindata.json] dosyasını güncellemek yeterli olacaktır. Sürüm 01'de ise koda girip vergi dilimlerini ve hesaplama sabitlerini değiştirmek gerekir. Oysa vergi dilimlerinin ve hesaplama sabitlerinin değerlerini değiştirmek zorunda olan kişilerin algoritmanın koduna erişimi olmayacağı muhtemeldir.