4. تمرین عملی – IMPOTS
4.1. مسئله
ما باید برنامهای بنویسیم تا بدهی مالیاتی یک مؤدی را محاسبه کند. ما مورد سادهشدهای را در نظر میگیریم که مؤدی تنها حقوق خود را برای اظهار دارد:
- تعداد سهام برای کارمند به صورت nbParts = nbEnfants/2 + 1 در صورتی که متأهل نباشد، محاسبه میشود، nbEnfants/2 + 2 اگر متأهل باشند، که در آن nbEnfants تعداد فرزندانشان است.
- درآمد مشمول مالیات او R به صورت R = 0.72 × S محاسبه میشود، که در آن S حقوق سالانه او است.
- ما ضریب کمکهزینه خانوادگی او را Q = R/N محاسبه میکنیم
ما مالیات I او را بر اساس دادههای زیر محاسبه میکنیم
12620.0 | 0 | 0 |
۱۳٬۱۹۰ | 0.05 | ۶۳۱ |
۱۵٬۶۴۰ | 0.1 | ۱٬۲۹۰٫۵ |
۲۴٬۷۴۰ | 0.15 | ۲٬۰۷۲٫۵ |
۳۱٬۸۱۰ | 0.2 | ۳٬۳۰۹٫۵ |
۳۹٬۹۷۰ | 0.25 | ۴٬۹۰۰ |
۴۸٬۳۶۰ | 0.3 | ۶۸۹۸.۵ |
۵۵٬۷۹۰ | 0.35 | ۹٬۳۱۶٫۵ |
۹۲٬۹۷۰ | 0.4 | ۱۲٬۱۰۶ |
۱۲۷٬۸۶۰ | 0.45 | ۱۶٬۷۵۴٫۵ |
۱۵۱٬۲۵۰ | 0.50 | ۲۳٬۱۴۷٫۵ |
۱۷۲٬۰۴۰ | 0.55 | ۳۰٬۷۱۰ |
۱۹۵٬۰۰۰ | 0.60 | ۳۹٬۳۱۲ |
0 | 0.65 | ۴۹٬۰۶۲ |
هر سطر شامل ۳ فیلد است. برای محاسبه مالیات I، به دنبال اولین سطری میگردیم که QF ≤ field1 باشد. برای مثال، اگر QF = 30000 باشد، سطر را پیدا خواهیم کرد
مالیات I سپس برابر است با 0.15*R - 2072.5*nbParts. اگر QF به گونهای باشد که شرط QF <= field1 هرگز برقرار نشود، ضرایب مربوط به آخرین خط استفاده میشوند. در این صورت:
که مالیات I = 0.65*R – 49062*nbParts را به دست میدهد.
4.2. نسخه با استفاده از آرایهها (impots_01)
ما یک برنامهٔ اولیه ارائه میدهیم که در آن:
- دادههای مورد نیاز برای محاسبه مالیات در سه آرایه (limits, 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);
//بازیابی سه فیلد «married»، «children» و «salary» که $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;
// نیم سهم اضافی در صورت وجود حداقل سه فرزند
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
نظرات
- خط ۴: نام فایل متنی حاوی جزئیات مالیاتدهندگان (وضعیت تأهل، فرزندان، حقوق)
- خط ۵: نام فایل متنی حاوی نتایج (وضعیت تأهل، فرزندان، حقوق، مالیات) محاسبه مالیات
- خطوط ۶–۸: سه جدول دادهای مورد استفاده برای محاسبه مالیات
- خطوط ۱۱–۱۵: باز کردن فایل دادههای مالیاتدهنده در حالت فقط خواندنی
- خطوط ۱۸–۲۲: باز کردن فایل نتایج برای نوشتن
- خط ۲۵: حلقه برای خواندن خطوط (وضعیت تأهل، تعداد فرزندان، حقوق) از فایل داده مودی مالیاتی
- خط ۲۷: کاراکتر پایان خط حذف میشود
- خط ۲۹: اجزای خط (وضعیت تأهل، تعداد فرزندان، حقوق) بازیابی میشوند
- خط ۳۱: مالیات محاسبه میشود
- خط ۳۳: مالیات در فایل نتایج ذخیره میشود
- خطوط ۳۷–۳۸: پس از پردازش کامل فایل مالیاتدهنده، فایلها بسته میشوند
- خط ۴۴: تابع حذف کاراکتر پایان خط از یک خط $ligne. کاراکتر پایان خط در سیستمهای ویندوز رشته "\r\n" و در سیستمهای یونیکس "\n" است. نتیجه، رشته ورودی بدون کاراکتر پایان خط آن است.
- خطوط ۴۷–۴۸: `substr($chaîne,$début,$taille) زیر رشتهای از $chaîne است که از کاراکتر $début شروع شده و حداکثر $taille کاراکتر دارد.
- خط ۶۳:
strtolower($chaîne)$chaîneرا به حروف کوچک تبدیل میکند - خط ۷۶: array_push($tableau,$élément) مقدار $élément را به انتهای آرایه $tableau اضافه میکند. توجه داشته باشید که آرایه $limites به صورت مقدار به تابع calculerImpot (خط 56: )) پاس میشود. بنابراین، افزودن این عنصر بر روی یک کپی از پارامتر واقعی انجام میشود که بدون تغییر باقی میماند.
- خط ۸۴: تابع 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;
}//اگر
// خواندن دادههای کاربر
...
//پایان
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","","","");
// ایجاد ۳ جدول – با فرض درست بودن نحوی سطرها
$limites = explode(":", cutNewLineChar($tables[0]));
$coeffR = explode(":", cutNewLineChar($tables[1]));
$coeffN = explode(":", cutNewLineChar($tables[2]));
//پایان
return array("", $limites, $coeffR, $coeffN);
}
?>
توضیحات
- خط ۱۱: تابع getTables($IMPOTS) فایل متنی $IMPOTS را پردازش میکند تا سه آرایه را استخراج کند ($limites, $coeffR, $coeffN). نتیجه بازگردانده شده عبارت است از ($erreur, $limites, $coeffR, $coeffN)، که در آن $erreur یک پیام خطا است، که در صورت عدم وقوع خطا خالی است.
- خط ۴۰: تابع getTables($IMPOTS).
- خط ۴۳: تابع files_exists(nom_fichier) اگر فایل nom_fichier وجود داشته باشد، مقدار بولی true را برمیگرداند و در غیر این صورت مقدار بولی false را برمیگرداند.
- خط ۴۶: تابع
file(nom\_fichier)کل فایل متنیnom\_fichierرا میخواند. این تابع یک آرایه بازمیگرداند که هر عنصر آن یک خط از فایل متنی است. از آنجا که فایلimpots.txtسه خط متن دارد، این تابع یک آرایه با سه عنصر بازمیگرداند. - خطوط ۵۰–۵۲: سه خط بازیابیشده برای ایجاد سه آرایه ($limites, $coeffR, $coeffN) استفاده میشوند
نتایج بهدستآمده با نتایج نسخه قبلی یکسان هستند.