4. Практичне завдання — IMPOTS
4.1. Задача
Задано написати програму, яка дозволяє обчислити податок платника податків. Розглянемо спрощений випадок, коли платник податків має задекларувати лише свою заробітну плату:
- кількість часток працівника обчислюється за формулою nbParts = nbEnfants/2 + 1, якщо він не одружений, nbEnfants/2+2, якщо він одружений, де nbEnfants — кількість його дітей.
- розраховується його оподатковуваний дохід 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 |
195 000 | 0,60 | 39312 |
0 | 0,65 | 49062 |
Кожен рядок має 3 поля. Щоб обчислити податок I, шукаємо перший рядок, у якому QF <= поле1. Наприклад, якщо QF = 30000, то знайдемо рядок
Тоді податок I дорівнює 0,15*R - 2072,5*nbParts. Якщо QF є таким, що співвідношення QF<=поле1 ніколи не виконується, то використовуються коефіцієнти останнього рядка. У даному випадку:
що дає податок I=0,65*R – 49062*nbParts.
4.2. Версія з таблицями (impots_01)
Ми пропонуємо першу програму, в якій:
- дані, необхідні для розрахунку податку, містяться у трьох масивах (limites, coeffR, coeffN)
- дані про платників податків (сімейний стан, діти, заробітна плата) містяться в першому текстовому файлі
- результати розрахунку податку (сімейний стан, діти, заробітна плата, податок) зберігаються у другому текстовому файлі
<?php
// визначення констант
$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);
// читання даних
$data = fopen($DATA, "r");
if (!$data) {
print "Impossible d'ouvrir en lecture le fichier des données [$DATA]\n";
exit;
}
// відкриття файлу результатів
$résultats = fopen($RESULTATS, "w");
if (!$résultats) {
print "Impossible de créer le fichier des résultats [$RESULTATS]\n";
exit;
}
// обробка поточного рядка файлу даних
while ($ligne = fgets($data, 100)) {
// видалення можливого символу кінця рядка
$ligne = cutNewLineChar($ligne);
// витягуються 3 поля «одружений», «діти», «зарплата», що утворюють $ligne
list($marié, $enfants, $salaire) = explode(",", $ligne);
// розраховується податок
$impôt = calculImpots($marié, $enfants, $salaire, $limites, $coeffR, $coeffN);
// записуємо результат у файл результатів
fputs($résultats, "$marié:$enfants:$salaire:$impôt\n");
// наступний платник податків
}
// закриваємо файли
fclose($data);
fclose($résultats);
// кінець
exit;
// --------------------------------------------------------------------------
function cutNewLinechar($ligne) {
// видаляється маркер кінця рядка з $ligne, якщо він існує
$L = strlen($ligne); // довжина рядка
while (substr($ligne, $L - 1, 1) == "\n" or substr($ligne, $L - 1, 1) == "\r") {
$ligne = substr($ligne, 0, $L - 1);
$L--;
}
// кінець
return($ligne);
}
// --------------------------------------------------------------------------
function calculImpots($marié, $enfants, $salaire, $limites, $coeffR, $coeffN) {
// $marié: так, ні
// $enfants: кількість дітей
// $salaire: річний оклад
// $limites, $coeffR, $coeffN: таблиці даних, що дозволяють розрахувати податок
// кількість часток
$marié = strtolower($marié);
if ($marié == "oui")
$nbParts = $enfants / 2 + 2;
else
$nbParts=$enfants / 2 + 1;
// на 1/2 частки більше, якщо є щонайменше 3 дітей
if ($enfants >= 3)
$nbParts+=0.5;
// оподатковуваний дохід
$revenuImposable = 0.72 * $salaire;
// сімейний коефіцієнт
$quotient = $revenuImposable / $nbParts;
// вказується в кінці таблиці обмежень для припинення наступного циклу
array_push($limites, $quotient);
// розрахунок податку
$i = 0;
while ($quotient > $limites[$i])
$i++;
// оскільки $quotient розміщено в кінці таблиці $limites, попередній цикл
// не може виходити за межі масиву $limites
// тепер можна обчислити податок
return floor($revenuImposable * $coeffR[$i] - $nbParts * $coeffN[$i]);
}
?>
Файл даних data.txt (статус шлюбу, діти, заробітна плата):
Файли résultats.txt (сімейний стан, діти, заробітна плата, податок) з отриманими результатами:
oui:2:200000:22504
non:2:200000:33388
oui:3:200000:16400
non:3:200000:22504
oui:5:50000:0
non:0:3000000:1354938
Коментарі
- рядок 4: назва текстового файлу, що містить дані про платників податків (статус шлюбу, діти, заробітна плата)
- рядок 5: ім’я текстового файлу, що містить результати (статус у шлюбі, діти, заробітна плата, податок) розрахунку податку
- рядки 6–8: три таблиці даних, що дозволяють розрахувати податок
- рядки 11–15: відкриття файлу з даними платників податків у режимі читання
- рядки 18–22: відкриття файлу результатів для запису
- рядок 25: цикл читання рядків (сімейний стан, діти, заробітна плата) з файлу даних про платників податків
- рядок 27: видалення позначки кінця рядка
- рядок 29: витягуються складові (статус одруженого, діти, заробітна плата) рядка
- рядок 31: обчислюється податок
- рядок 33: податок записується у файл результатів
- рядки 37–38: після повного опрацювання файлу платників податків файли закриваються
- рядок 44: функція, яка видаляє маркер кінця рядка з рядка $ligne. Маркером кінця рядка є рядок "\r\n" у системах Windows та "\n" у системах Unix. Результатом є вхідний рядок без маркера кінця рядка.
- рядки 47–48: substr($chaîne,$début,$taille) — це підрядок рядка $chaîne, що починається з символу $début і містить не більше $taille символів.
- рядок 63: strtolower($chaîne) перетворює $chaîne на малі літери
- рядок 76: array_push($tableau,$élément) додає $élément у кінець масиву $tableau. Слід зауважити, що масив $limites передається за значенням у функцію calculerImpot (рядок 56)). Отже, додавання елемента відбувається до копії фактичного параметра, який залишається незмінним.
- рядок 84: функція floor($x) повертає ціле значення, безпосередньо менше за $x.
4.3. Версія з текстовими файлами (impots_02)
Ця нова версія відрізняється від попередньої лише тим, що дані ($limites, $coeffR, $coeffN), необхідні для розрахунку податку, тепер містяться у текстовому файлі у такому вигляді:
Файл 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
Нова версія просто зчитує дані з файлу [impots.txt], щоб помістити їх у три таблиці ($limites, $coeffR, $coeffN). Отже, ми повертаємося до попереднього випадку. Наводимо лише зміни:
<?php
// визначення констант
$DATA = "data.txt";
$RESULTATS = "resultats.txt";
$IMPOTS = "impots.txt";
// дані, необхідні для розрахунку податку, були розміщені у файлі $IMPOTS
// по одному рядку на таблицю у вигляді
// val1:val2:val3,...
list($erreur, $limites, $coeffR, $coeffN) = getTables($IMPOTS);
// Чи сталася помилка?
if ($erreur) {
print "$erreur\n";
exit;
}//if
// читання даних користувача
...
// кінець
exit;
// --------------------------------------------------------------------------
function cutNewLinechar($ligne) {
// видаляємо маркер кінця рядка з $ligne, якщо він існує
...
}
// --------------------------------------------------------------------------
function calculImpots($marié, $enfants, $salaire, $limites, $coeffR, $coeffN) {
// $marié: так, ні
// $enfants: кількість дітей
// $salaire: річний оклад
// $limites, $coeffR, $coeffN: таблиці даних, що дозволяють розрахувати податок
...
}
// --------------------------------------------------------------------------
function getTables($IMPOTS) {
// $IMPOTS: назва файлу, що містить дані з таблиць $limites, $coeffR, $coeffN
// чи існує файл $IMPOTS?
if (!file_exists($IMPOTS))
return array("Le fichier $IMPOTS n'existe pas","","","");
// блокове читання файлу
$tables = file($IMPOTS);
if (!$tables)
return array("Erreur lors de l'exploitation du fichier $IMPOTS","","","");
// створення 3 таблиць — припускаємо, що рядки синтаксично правильні
$limites = explode(":", cutNewLineChar($tables[0]));
$coeffR = explode(":", cutNewLineChar($tables[1]));
$coeffN = explode(":", cutNewLineChar($tables[2]));
// кінець
return array("", $limites, $coeffR, $coeffN);
}
?>
Коментарі
- рядок 11: функція getTables($IMPOTS) обробляє текстовий файл $IMPOTS, щоб витягти з нього три масиви ($limites, $coeffR, $coeffN). Результат, що повертається, — це ($erreur, $limites, $coeffR, $coeffN), де $erreur — це повідомлення про помилку, яке залишається порожнім, якщо помилки не сталося.
- рядок 40: функція getTables($IMPOTS).
- рядок 43: функція files_exists(nom_fichier) повертає логічне значення true, якщо файл nom_fichier існує, і логічне значення false — у протилежному випадку.
- рядок 46: функція file(nom_fichier) зчитує весь текстовий файл nom_fichier. Вона повертає масив, кожен елемент якого є рядком текстового файлу. Оскільки в даному випадку файл impots.txt містить три рядки тексту, функція поверне масив із трьома елементами.
- рядки 50–52: використання трьох отриманих рядків для створення трьох масивів ($limites, $coeffR, $coeffN)
Отримані результати збігаються з результатами попередньої версії.