4. Ejercicio de aplicación - TAXES
4.1. El problema
Nuestro objetivo es escribir un programa para calcular los impuestos de un contribuyente. Consideraremos el caso simplificado de un contribuyente que sólo tiene que declarar su sueldo:
- El número de acciones para el empleado se calcula as nbParts = nbEnfants / 2 + 1 si no están casados, o nbEnfants / 2 + 2 si están casados, dónde nbEnfants es el número de hijos que tienen.
- Calculamos su base imponible R = 0,72 * S, donde S es su salario anual
- Calculamos su coeficiente familiar Q = R / N
Calculamos su impuesto I basándonos en los siguientes datos
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 | 4900 |
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 |
Cada fila tiene 3 campos. Para calcular el impuesto I, buscamos la primera fila donde QF <= campo1. Por ejemplo, si QF = 30000, encontraremos la fila
El impuesto I es igual a 0.15*R - 2072.5*nbParts. Si QF es tal que la condición QF<=field1 nunca se cumple, entonces se utilizan los coeficientes de la última fila. Aquí:
lo que da el impuesto I = 0,65*R - 49062*nbParts.
4.2. Versión con matrices (impots_01)
Presentamos un programa inicial en el que:
- los datos necesarios para calcular el impuesto están en tres matrices (límites, coeffR, coeffN)
- los datos del contribuyente (casado, hijos, salario) están en un primer fichero de texto
- los resultados del cálculo fiscal (casado, hijos, salario, impuestos) se almacenan en un segundo archivo de texto
1. <?php
2.
3. // definition of constants
4. $DATA = "data.txt";
5. $RESULTS = "results.txt";
6. $limits = array(12620, 13190, 15640, 24740, 31810, 39970, 48360, 55790, 92970, 127860, 151250, 172040, 195000);
7. $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);
8. $coeffN = array(0, 631, 1290.5, 2072.5, 3309.5, 4900, 6898.5, 9316.5, 12106, 16754.5, 23147.5, 30710, 39312, 49062);
9.
10. // Read data
11. $data = fopen($DATA, "r");
12. if (!$data) {
13. print "Unable to open the data file [$DATA] for reading\n";
14. exit;
15. }
16.
17. // Open the results file
18. $results = fopen($RESULTS, "w");
19. if (!$results) {
20. print "Unable to create the results file [$RESULTS]\n";
21. exit;
22. }
23.
24. // process the current line of the data file
25. while ($line = fgets($data, 100)) {
26. // remove any end-of-line characters
27. $line = cutNewLineChar($line);
28. // retrieve the 3 fields married, children, salary that make up $line
29. list($married, $children, $salary) = explode(",", $line);
30. // calculate the tax
31. $tax = calculateTaxes($married, $children, $salary, $limits, $coeffR, $coeffN);
32. // write the result to the results file
33. fputs($results, "$married:$children:$salary:$tax\n");
34. // next taxpayer
35. }
36. // close the files
37. fclose($data);
38. fclose($results);
39.
40. // end
41. exit;
42.
43. // --------------------------------------------------------------------------
44. function cutNewLinechar($line) {
45. // remove the end-of-line character from $line if it exists
46. $L = strlen($line); // line length
47. while (substr($line, $L - 1, 1) == "\n" or substr($line, $L - 1, 1) == "\r") {
48. $line = substr($line, 0, $L - 1);
49. $L--;
50. }
51. // end
52. return($line);
53. }
54.
55. // --------------------------------------------------------------------------
56. function calculateTaxes($married, $children, $salary, $thresholds, $coeffR, $coeffN) {
57. // $married: yes, no
58. // $children: number of children
59. // $salary: annual salary
60. // $limits, $coeffR, $coeffN: data arrays used to calculate taxes
61.
62. // number of shares
63. $married = strtolower($married);
64. if ($married == "yes")
65. $nbParts = $children / 2 + 2;
66. else
67. $nbParts = $children / 2 + 1;
68. // add 1/2 share if there are at least 3 children
69. if ($children >= 3)
70. $nbParts+=0.5;
71. // taxable income
72. $taxableIncome = 0.72 * $salary;
73. // family quotient
74. $quotient = $taxableIncome / $numberOfChildren;
75. // is added to the end of the limits array to stop the following loop
76. array_push($limits, $quotient);
77. // tax calculation
78. $i = 0;
79. while ($quotient > $limits[$i])
80. $i++;
81. // Since we placed $quotient at the end of the $limites array, the previous loop
82. // cannot go beyond the bounds of the $limits array
83. // now we can calculate the tax
84. return floor($taxableIncome * $rate[$i] - $numberOfShares * $taxRate[$i]);
85. }
86. ?>
El fichero de datos data.txt (casado, hijos, salario):
En results.txt (casados, hijos, salario, impuestos) por los resultados obtenidos:
yes:2:200000:22504
no:2:200000:33388
yes:3:200000:16400
no:3:200000:22504
yes:5:50000:0
no:0:3000000:1354938
Comentarios
- línea 4: nombre del fichero de texto que contiene los datos del contribuyente (casado, hijos, salario)
- línea 5: nombre del archivo de texto que contiene los resultados (casado, hijos, salario, impuestos) del cálculo de impuestos
- Líneas 6-8: las tres tablas de datos utilizadas para calcular el impuesto
- líneas 11-15: abrir el fichero de datos del contribuyente para su lectura
- líneas 18-22: abrir el fichero de resultados para escribir
- línea 25: bucle para leer las líneas (casado, hijos, salario) del fichero de contribuyentes
- línea 27: se elimina el carácter de fin de línea
- línea 29: se recuperan los componentes (casado, hijos, salario) de la línea
- línea 31: se calcula el impuesto
- línea 33: el impuesto se almacena en el fichero de resultados
- líneas 37-38: una vez que el expediente del contribuyente se ha tramitado en su totalidad, se cierran los expedientes
- línea 44: la función que elimina el carácter de fin de línea de una línea $línea. El carácter de fin de línea es la cadena "\r\n" en sistemas Windows, "\n" en sistemas Unix. El resultado es la cadena de entrada sin su carácter de fin de línea.
- líneas 47-48: substr($cadena, $inicio, $tamaño) devuelve la subcadena de $cadena a partir del carácter inicio y que contenga como máximo $tamaño personajes.
- línea 63: strtolower($cadena) convierte $cadena a minúsculas
- línea 76: array_push($array, $elemento) añade $elemento hasta el final de el $array. Tenga en cuenta que el $límites se pasa por valor a la matriz calculateTax función (línea 56). Esta adición de un elemento se realiza, por tanto, sobre una copia del parámetro real, que permanece inalterado.
- línea 84: la función suelo($x) devuelve el valor entero inmediatamente inferior a $x.
4.3. Versión con archivos de texto (impots_02)
Esta nueva versión difiere de la anterior únicamente en que los datos ($limites, $coeffR, $coeffN) necesarios para calcular el impuesto se encuentran ahora en un fichero de texto con el siguiente formato:
Archivo 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 nueva versión simplemente lee los datos del archivo [impots.txt] y los coloca en tres matrices ($limits, $coeffR, $coeffN). Esto nos devuelve al caso anterior. Presentamos sólo los cambios:
1. <?php
2.
3. // definition of constants
4. $DATA = "data.txt";
5. $RESULTS = "results.txt";
6. $TAXES = "taxes.txt";
7.
8. // The data needed to calculate the tax has been placed in the $IMPOTS file
9. // with one line per table in the form
10. // val1:val2:val3,...
11. list($error, $limits, $coeffR, $coeffN) = getTables($TAXES);
12.
13. // Was there an error?
14. if ($error) {
15. print "$error\n";
16. exit;
17. }//if
18. // reading user data
19. ...
20.
21. // end
22. exit;
23.
24. // --------------------------------------------------------------------------
25. function cutNewLinechar($line) {
26. // remove the end-of-line character from $line if it exists
27. ...
28. }
29.
30. // --------------------------------------------------------------------------
31. function calculateTaxes($married, $children, $salary, $thresholds, $coeffR, $coeffN) {
32. // $married: yes, no
33. // $children: number of children
34. // $salary: annual salary
35. // $limits, $coeffR, $coeffN: data arrays used to calculate taxes
36. ...
37. }
38.
39. // --------------------------------------------------------------------------
40. function getTables($IMPOTS) {
41. // $IMPOTS: the name of the file containing the data for the $limites, $coeffR, and $coeffN tables
42. // Does the $IMPOTS file exist?
43. if (!file_exists($IMPOTS))
44. return array("The $IMPOTS file does not exist","","","");
45. // read the file in blocks
46. $tables = file($IMPOTS);
47. if (!$tables)
48. return array("Error while processing the $IMPOTS file","","","");
49. // Create the 3 tables - assuming the lines are syntactically correct
50. $limits = explode(":", cutNewLineChar($tables[0]));
51. $coeffR = explode(":", cutNewLineChar($tables[1]));
52. $coeffN = explode(":", cutNewLineChar($tables[2]));
53. // end
54. return array("", $limits, $coeffR, $coeffN);
55. }
56. ?>
Comentarios
- Línea 11: La función getTables($IMPOTS) procesa el archivo de texto $IMPOTS para extraer las tres tablas ($limits, $coeffR, $coeffN). El resultado devuelto es ($error, $limits, $coeffR, $coeffN), donde $error es un mensaje de error; está vacío si no se ha producido ningún error.
- Línea 40: El getTables($IMPOTS) función.
- línea 43: la función files_exists(nombre de archivo) devuelve el booleano verdadero si el archivo nombre de archivo existe, y falso de lo contrario.
- línea 46: el archivo(nombrearchivo) lee todo el archivo de texto nombre de archivo. Devuelve una matriz en la que cada elemento es una línea del archivo de texto. Dado que el impots.txt tiene tres líneas de texto, la función devolverá una matriz con tres elementos.
- Líneas 50-52: Utiliza las tres líneas recuperadas para crear las tres matrices ($limits, $coeffR, $coeffN)
Los resultados obtenidos son los mismos que los de la versión anterior.