4. Esercizio pratico – Calcolo delle imposte
4.1. Il problema
Il nostro obiettivo è scrivere un programma per calcolare l'imposta di un contribuente. Prenderemo in considerazione il caso semplificato di un contribuente che deve dichiarare solo il proprio stipendio:
- Il numero di quote per il dipendente è calcolato come nbParts = nbEnfants / 2 + 1 se è celibe, oppure nbEnfants / 2 + 2 se è coniugato, dove nbEnfants è il numero di figli che ha.
- Calcoliamo il loro reddito imponibile R = 0,72 * S, dove S è il loro stipendio annuale
- Calcoliamo il loro coefficiente familiare Q = R / N
Calcoliamo la loro imposta I sulla base dei seguenti dati
12620,0 | 0 | 0 |
13.190 | 0,05 | 631 |
15.640 | 0,1 | 1.290,5 |
24.740 | 0,15 | 2.072,5 |
31.810 | 0,2 | 3.309,5 |
39.970 | 0,25 | 4.900 |
48.360 | 0,3 | 6.898,5 |
55.790 | 0,35 | 9.316,5 |
92.970 | 0,4 | 12.106 |
127.860 | 0,45 | 16.754,5 |
151.250 | 0,50 | 23.147,5 |
172.040 | 0,55 | 30.710 |
195.000 | 0,60 | 39.312 |
0 | 0,65 | 49.062 |
Ogni riga ha 3 campi. Per calcolare l'imposta I, cerchiamo la prima riga in cui QF <= campo1. Ad esempio, se QF = 30000, troveremo la riga
L'imposta I è quindi pari a 0,15*R - 2072,5*nbParts. Se QF è tale che la condizione QF<=field1 non è mai soddisfatta, vengono utilizzati i coefficienti dell'ultima riga. Qui:
il che dà come risultato l'imposta I = 0,65*R – 49062*nbParts.
4.2. Versione con array (impots_01)
Presentiamo un programma iniziale in cui:
- i dati necessari per il calcolo delle imposte sono contenuti in tre array (limits, coeffR, coeffN)
- i dati del contribuente (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
// definition of constants
$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);
// reading data
$data = fopen($DATA, "r");
if (!$data) {
print "Impossible d'ouvrir en lecture le fichier des données [$DATA]\n";
exit;
}
// open results file
$résultats = fopen($RESULTATS, "w");
if (!$résultats) {
print "Impossible de créer le fichier des résultats [$RESULTATS]\n";
exit;
}
// use the current line of the data file
while ($ligne = fgets($data, 100)) {
// remove any end-of-line marker
$ligne = cutNewLineChar($ligne);
// we retrieve the 3 fields married,children,salary which form $ligne
list($marié, $enfants, $salaire) = explode(",", $ligne);
// tax calculation
$impôt = calculImpots($marié, $enfants, $salaire, $limites, $coeffR, $coeffN);
// enter the result in the results file
fputs($résultats, "$marié:$enfants:$salaire:$impôt\n");
// next taxpayer
}
// close files
fclose($data);
fclose($résultats);
// end
exit;
// --------------------------------------------------------------------------
function cutNewLinechar($ligne) {
// delete the end-of-line mark from $ligne if it exists
$L = strlen($ligne); // // line length
while (substr($ligne, $L - 1, 1) == "\n" or substr($ligne, $L - 1, 1) == "\r") {
$ligne = substr($ligne, 0, $L - 1);
$L--;
}
// end
return($ligne);
}
// --------------------------------------------------------------------------
function calculImpots($marié, $enfants, $salaire, $limites, $coeffR, $coeffN) {
// $marié : yes, no
// $enfants : number of children
// $salaire: annual salary
// $limites, $coeffR, $coeffN: tax calculation data tables
// number of shares
$marié = strtolower($marié);
if ($marié == "oui")
$nbParts = $enfants / 2 + 2;
else
$nbParts=$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
array_push($limites, $quotient);
// tAX CALCULATION
$i = 0;
while ($quotient > $limites[$i])
$i++;
// because $quotient has been placed at the end of the $limites array, the previous loop
// cannot exceed the table $limites
// now we can calculate the tax
return floor($revenuImposable * $coeffR[$i] - $nbParts * $coeffN[$i]);
}
?>
Il file di dati data.txt (stato civile, figli, stipendio):
I file results.txt (stato civile, figli, stipendio, imposte) relativi ai 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 del contribuente (stato civile, figli, stipendio)
- riga 5: il nome del file di testo contenente i risultati (stato civile, figli, stipendio, imposta) del calcolo fiscale
- Righe 6–8: le tre tabelle di dati utilizzate per calcolare l'imposta
- righe 11-15: aprono il file dei dati del contribuente per la lettura
- righe 18–22: aprono il file dei risultati per la scrittura
- riga 25: ciclo per leggere le righe (stato civile, figli, stipendio) dal file del contribuente
- riga 27: il carattere di fine riga viene rimosso
- riga 29: vengono recuperati i componenti (stato civile, figli, stipendio) della riga
- riga 31: si calcola l'imposta
- riga 33: l'imposta viene memorizzata nel file dei risultati
- righe 37-38: una volta che il file dei contribuenti è stato completamente elaborato, i file vengono chiusi
- riga 44: la funzione che rimuove il carattere di fine riga da una riga $line. 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($string, $start, $size) restituisce la sottostringa di $string che inizia dal carattere $start e contiene al massimo $size caratteri.
- riga 63: strtolower($string) converte $string in minuscolo
- riga 76: array_push($array, $element) aggiunge $element alla fine di $array. Si noti che l'array $limits viene passato per valore alla funzione calculateTax (riga 56). L'aggiunta di un elemento viene quindi eseguita su una copia del parametro effettivo, che rimane invariato.
- 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 calcolare l'imposta si trovano ora in un file di testo nel seguente formato:
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 legge semplicemente i dati dal file [impots.txt] e li inserisce in tre array ($limites, $coeffR, $coeffN). Questo ci riporta al caso precedente. Presentiamo solo le modifiche:
<?php
// 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,...
list($erreur, $limites, $coeffR, $coeffN) = getTables($IMPOTS);
// was there a mistake?
if ($erreur) {
print "$erreur\n";
exit;
}//if
// reading user data
...
// end
exit;
// --------------------------------------------------------------------------
function cutNewLinechar($ligne) {
// delete the end-of-line mark from $ligne if it exists
...
}
// --------------------------------------------------------------------------
function calculImpots($marié, $enfants, $salaire, $limites, $coeffR, $coeffN) {
// $marié : yes, no
// $enfants : number of children
// $salaire: annual salary
// $limites, $coeffR, $coeffN: tax calculation data tables
...
}
// --------------------------------------------------------------------------
function getTables($IMPOTS) {
// $IMPOTS: name of the file containing data from tables $limites, $coeffR, $coeffN
// does the $IMPOTS file exist?
if (!file_exists($IMPOTS))
return array("Le fichier $IMPOTS n'existe pas","","","");
// file block playback
$tables = file($IMPOTS);
if (!$tables)
return array("Erreur lors de l'exploitation du fichier $IMPOTS","","","");
// create the 3 tables - assume the rows are syntactically correct
$limites = explode(":", cutNewLineChar($tables[0]));
$coeffR = explode(":", cutNewLineChar($tables[1]));
$coeffN = explode(":", cutNewLineChar($tables[2]));
// end
return array("", $limites, $coeffR, $coeffN);
}
?>
Commenti
- Riga 11: La funzione getTables($IMPOTS) elabora il file di testo $IMPOTS per estrarre le tre tabelle ($limites, $coeffR, $coeffN). Il risultato restituito è ($error, $limites, $coeffR, $coeffN), dove $error è un messaggio di errore; è vuoto se non si è verificato alcun errore.
- Riga 40: La funzione getTables($IMPOTS).
- Riga 43: la funzione files_exists(filename) restituisce il valore booleano true se il file filename esiste, e false in caso contrario.
- Riga 46: la funzione file(filename) legge l'intero file di testo filename. Restituisce un array in cui ogni elemento è una riga del file di testo. Poiché il file impots.txt contiene tre righe di testo, la funzione restituirà un array con tre elementi.
- Righe 50–52: utilizzare le tre righe recuperate per creare i tre array ($limits, $coeffR, $coeffN)
I risultati ottenuti sono gli stessi di quelli ottenuti nella versione precedente.