Skip to content

4. Esercizio pratico - IMPOTS

4.1. Il problema

Si propone di scrivere un programma che consenta di calcolare l'imposta di un contribuente. Si considera il caso semplificato di un contribuente che abbia da dichiarare solo il proprio stipendio:

  • si calcola il numero di quote del dipendente nbParts = nbEnfants/2 + 1 se non è sposato, nbEnfants/2+2 se è sposato, dove nbEnfants è il numero dei suoi figli.
  • si calcola il suo reddito imponibile R=0,72*S, dove S è il suo stipendio annuale
  • si calcola il suo coefficiente familiare Q = R/N

si calcola la sua imposta I in base ai seguenti dati

12620,0
0
0
13.190
0,05
631
15640
0,1
1290,5
24.740
0,15
2072,5
31810
0,2
3309,5
39.970
0,25
4900
48360
0,3
6898,5
55790
0,35
9316,5
92970
0,4
12106
127.860
0,45
16754,5
151250
0,50
23147,5
172.040
0,55
30710
195.000
0,60
39312
0
0,65
49062

Ogni riga ha 3 campi. Per calcolare l'imposta I, si cerca la prima riga in cui QF<=campo1. Ad esempio, se QF=30000, si troverà la riga

    24740        0.15        2072.5

L'imposta I è quindi pari a 0,15*R - 2072,5*nbParts. Se QF è tale che la relazione QF<=campo1 non è mai soddisfatta, allora vengono utilizzati i coefficienti dell’ultima riga. In questo caso:

    0                0.65        49062

il che dà l’imposta I=0,65*R – 49062*nbParts.

4.2. Versione con tabelle (impots_01)

Presentiamo un primo programma in cui:

  • i dati necessari per il calcolo dell’imposta si trovano in tre tabelle (limiti, coeffR, coeffN)
  • i dati dei contribuenti (stato civile, figli, stipendio) si trovano in un primo file di testo
  • i risultati del calcolo dell’imposta (stato civile, figli, stipendio, imposta) sono memorizzati in un secondo file di testo

<?php

// definizione delle costanti
$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);

// lettura dei dati
$data = fopen($DATA, "r");
if (!$data) {
  print "Impossible d'ouvrir en lecture le fichier des données [$DATA]\n";
  exit;
}

// apertura del file dei risultati
$résultats = fopen($RESULTATS, "w");
if (!$résultats) {
  print "Impossible de créer le fichier des résultats [$RESULTATS]\n";
  exit;
}

// si elabora la riga corrente del file dei dati
while ($ligne = fgets($data, 100)) {
  // si rimuove l'eventuale carattere di fine riga
  $ligne = cutNewLineChar($ligne);
  // si recuperano i 3 campi «coniuge», «figli» e «stipendio» che formano $ligne
  list($marié, $enfants, $salaire) = explode(",", $ligne);
  // si calcola l’imposta
  $impôt = calculImpots($marié, $enfants, $salaire, $limites, $coeffR, $coeffN);
  // si inserisce il risultato nel file dei risultati
  fputs($résultats, "$marié:$enfants:$salaire:$impôt\n");
  // contribuente successivo
}
// si chiudono i file
fclose($data);
fclose($résultats);

// fine
exit;

// --------------------------------------------------------------------------
function cutNewLinechar($ligne) {
  // si elimina il carattere di fine riga da $ligne, se presente
  $L = strlen($ligne);  // lunghezza riga
  while (substr($ligne, $L - 1, 1) == "\n" or substr($ligne, $L - 1, 1) == "\r") {
    $ligne = substr($ligne, 0, $L - 1);
    $L--;
  }
  // fine
  return($ligne);
}

// --------------------------------------------------------------------------
function calculImpots($marié, $enfants, $salaire, $limites, $coeffR, $coeffN) {
  // $marié: sì, no
  // $enfants: numero di figli
  // $salaire: stipendio annuo
  // $limites, $coeffR, $coeffN: tabelle dei dati che consentono il calcolo dell'imposta
  
  // numero di quote
  $marié = strtolower($marié);
  if ($marié == "oui")
    $nbParts = $enfants / 2 + 2;
  else
    $nbParts=$enfants / 2 + 1;
  // una quota aggiuntiva di 1/2 se ci sono almeno 3 figli
  if ($enfants >= 3)
    $nbParts+=0.5;
  // reddito imponibile
  $revenuImposable = 0.72 * $salaire;
  // quoziente familiare
  $quotient = $revenuImposable / $nbParts;
  // viene inserito alla fine della tabella dei limiti per interrompere il ciclo successivo
  array_push($limites, $quotient);
  // calcolo dell’imposta
  $i = 0;
  while ($quotient > $limites[$i])
    $i++;
  // poiché $quotient è stato inserito alla fine della tabella $limites, il ciclo precedente
  // non può andare oltre i limiti della tabella $limites
  // ora è possibile calcolare l’imposta
  return floor($revenuImposable * $coeffR[$i] - $nbParts * $coeffN[$i]);
}
?>

Il file dei dati data.txt (stato civile, figli, stipendio):

oui,2,200000
non,2,200000
oui,3,200000
non,3,200000
oui,5,50000
non,0,3000000

I file résultats.txt (stato civile, figli, stipendio, imposte) dei risultati ottenuti:

oui:2:200000:22504
non:2:200000:33388
oui:3:200000:16400
non:3:200000:22504
oui:5:50000:0
non:0:3000000:1354938

Commenti

  • riga 4: il nome del file di testo contenente i dati dei contribuenti (stato civile, figli, stipendio)
  • riga 5: il nome del file di testo contenente i risultati (stato civile, figli, stipendio, imposta) del calcolo dell'imposta
  • righe 6-8: le tre tabelle di dati che consentono il calcolo dell’imposta
  • righe 11-15: apertura in lettura del file dei dati dei contribuenti
  • righe 18-22: apertura in scrittura del file dei risultati
  • riga 25: ciclo di lettura delle righe (stato civile, figli, stipendio) del file dei contribuenti
  • riga 27: il carattere di fine riga viene rimosso
  • riga 29: vengono recuperate le componenti (coniuge, figli, stipendio) della riga
  • riga 31: viene calcolata l'imposta
  • riga 33: l'imposta viene memorizzata nel file dei risultati
  • righe 37-38: una volta elaborato completamente il file dei contribuenti, i file vengono chiusi
  • riga 44: la funzione che rimuove il carattere di fine riga da una riga $ligne. Il carattere di fine riga è la stringa "\r\n" sui sistemi Windows, "\n" sui sistemi Unix. Il risultato è la stringa di input senza il carattere di fine riga.
  • righe 47-48: substr($chaîne,$début,$taille) è la sottostringa di $chaîne che inizia dal carattere $début e contiene al massimo $taille caratteri.
  • riga 63: strtolower($chaîne) restituisce $chaîne in minuscolo
  • riga 76: array_push($tableau,$élément) aggiunge $élément alla fine dell'array $tableau. Si noti che la tabella $limites è stata passata per valore alla funzione calculerImpot (riga 56: )). L’aggiunta di questo elemento avviene quindi sulla copia del parametro effettivo, che rimane inalterato.
  • riga 84: la funzione floor($x) restituisce il valore intero immediatamente inferiore a $x.

4.3. Versione con file di testo (impots_02)

Questa nuova versione differisce dalla precedente solo per il fatto che i dati ($limites, $coeffR, $coeffN) necessari per il calcolo dell’imposta si trovano ora in un file di testo nella forma seguente:

File 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

La nuova versione si limita a leggere i dati dal file [impots.txt] per inserirli in tre tabelle ($limites, $coeffR, $coeffN). Ci si ritrova quindi nella situazione precedente. Riportiamo solo le modifiche:


<?php

// definizione delle costanti
$DATA = "data.txt";
$RESULTATS = "resultats.txt";
$IMPOTS = "impots.txt";

// i dati necessari per il calcolo dell'imposta sono stati inseriti nel file $IMPOTS
// con una riga per ogni tabella nella forma
// val1:val2:val3,...
list($erreur, $limites, $coeffR, $coeffN) = getTables($IMPOTS);

// Si è verificato un errore?
if ($erreur) {
  print "$erreur\n";
  exit;
}//if
// lettura dei dati utente
...

// fine
exit;

// --------------------------------------------------------------------------
function cutNewLinechar($ligne) {
  // si rimuove il carattere di fine riga da $ligne se presente
...
}

// --------------------------------------------------------------------------
function calculImpots($marié, $enfants, $salaire, $limites, $coeffR, $coeffN) {
  // $marié: sì, no
  // $enfants: numero di figli
  // $salaire: stipendio annuo
  // $limites, $coeffR, $coeffN: tabelle dei dati che consentono il calcolo dell'imposta
  ...
}

// --------------------------------------------------------------------------
function getTables($IMPOTS) {
  // $IMPOTS: il nome del file contenente i dati delle tabelle $limites, $coeffR, $coeffN
  // Il file $IMPOTS esiste?
  if (!file_exists($IMPOTS))
    return array("Le fichier $IMPOTS n'existe pas","","","");
  // lettura in blocco del file
  $tables = file($IMPOTS);
  if (!$tables)
    return array("Erreur lors de l'exploitation du fichier $IMPOTS","","","");
  // creazione delle 3 tabelle - si presume che le righe siano sintatticamente corrette
  $limites = explode(":", cutNewLineChar($tables[0]));
  $coeffR = explode(":", cutNewLineChar($tables[1]));
  $coeffN = explode(":", cutNewLineChar($tables[2]));
  // fine
  return array("", $limites, $coeffR, $coeffN);
}
?>

Commenti

  • riga 11: la funzione getTables($IMPOTS) utilizza il file di testo $IMPOTS per estrarne le tre tabelle ($limites, $coeffR, $coeffN). Il risultato restituito è ($erreur, $limites, $coeffR, $coeffN), dove $erreur è un messaggio di errore, vuoto se non si è verificato alcun errore.
  • riga 40: la funzione getTables($IMPOTS).
  • riga 43: la funzione files_exists(nom_fichier) restituisce il valore booleano true se il file nom_fichier esiste, altrimenti il valore booleano false.
  • riga 46: la funzione file(nom_fichier) legge l'intero file di testo nom_fichier. Restituisce un array in cui ogni elemento corrisponde a una riga del file di testo. Poiché in questo caso il file impots.txt contiene tre righe di testo, la funzione restituirà un array composto da tre elementi.
  • righe 50-52: utilizzo delle tre righe recuperate per creare i tre array ($limites, $coeffR, $coeffN)

I risultati ottenuti sono gli stessi di quelli della versione precedente.