jump to navigation

Codigo autodocumentado (Self-documenting Code) October 6, 2007

Posted by karlsauter in Programación I.
add a comment

Términos generales

Documentación

Palabras clave

Comentarios, técnicas para comentar, documentación interna.

  1. INTRODUCCION

  2. El siguiente documento contiene una descripción de varias técnicas para realizar comentarios. En cada una de ellas se mencionan sus ventajas y desventajas. El objetivo es dar al lector una perspectiva de qué son buenos comentarios y porque son necesarios.

  3. COMENTAR O NO

    Esta pregunta ha traído muchas discusiones entre programadores, ya que los malos comentarios dificultan el trabajo. Pero la verdad es que buenos comentarios pueden prestar mucha ayuda a la hora de depurar el código y a la hora de hacerlo (ya verá por qué).

    Características de un buen comentario

    • NO REPITE EL CODIGO!!!!!

    • Explica la INTENCION del código.

    • No es exageradamente largo, ni le falta información.

    • Tiene un estilo fácil de modificar.

    Algunos autores dan recomendaciones como éstas:

    • No llene su código con comentarios de bajo nivel línea por línea.”[2]

    • Los comentarios son necesarios como párrafos explicativos.”[3]

    Mal comentario:

    // set product to "base"
    
    product = base;// loop from 2 to "num"
    
    for ( int i = 2; i <= num; i++ ) {
    
       // multiply "base" by "product"
    
       product = product * base;
    
    }
    
    System.out.println("Product = " + product);

    Buen comentario:

    // compute the square root of Num using the Newton-Raphson approximation
    
    r = num / 2;
    
    while ( abs( r - (num/r) ) > TOLERANCE ) {
    
       r = 0.5 * ( r + (num/r) );
    
    }
    
    System.out.println( "r = " + r );
  4. TECNICAS PARA COMENTAR

    • Enfóquese en el por qué más que en el cómo.

    • Prepare al lector para lo que sigue.

    • Haga que cada comentario valga la pena.

    • Documente sorpresas.

    • Eluda abrviaciones.

    • Diferencie entre comentarios mayores y menores.

    • Comentar cualquier error o usos indocumentados en un lenguaje o ambiente de desarrollo.

    • Justifique las violaciones de un estilo de programación adecuado.

    • No comente código malo, reescríbalo.

  5. Comentarios de lineas individuales

    Normalmente no se debe usar ya que es difícil decir algo útil sobre una sola línea de código. Las únicas razones válidas para usarlos es que el código de una línea sea muy complicado y no se pueda hacer más entendible o que la línea antes haya tenido un error y se quiera hacer un record del mismo (para lo cual es mejor tener un registro de errores a parte de todas formas).

    Comentarios de final de línea

    A veces son útiles, pero usualmente presentan problemas. A menos que se alineen a la derecha del código con tabs hacen ver el código desordenado y no son fáciles de identificar. Alinearlos a la derecha del código es problemático y hace que sea necesario modificarlos si una línea que tenga uno es modificada.

    Estos comentarios no se deben usar para notas de mantenimiento, ni para múltiples líneas de código. Sólo deben ser usados para líneas individuales en el caso de que se quiera documentar declaraciones o marcar el final de bloques de código.

    Ejemplo de uso correcto:

    int boundary = 0;         // upper index of sorted part of arrayString insertVal = BLANK; // data elmt to insert in sorted part of array
    
    int insertPos = 0;        // position to insert elmt in sorted part of array

    Comentarios de bloques

    Estos comentario siempre deben explicar la intención o el propósito del párrafo del bloque de código que le sigue. Deben decir cosas que el código mismo no puede. A pesar de que estos comentarios dan muchas explicaciones es mejor mantenerlos cortos haciendo un mayor esfuerzo en que el código mismo se documente y no en los comentarios.

    Algunas pautas a tener en cuenta:

    Comentarios de declaraciones de datos

    En las declaraciones debeme documentar las unidades y el rango de datos numéricos, los números en nombres de variables que representan un código que no se entiende sin comentar, limitaciones de entradas de usuario, variables con significado en cada bit y variables globales.

    Comentarios de estructuras de control

    Las estructuras de control deben documentarse para indicar su propósito y el motivo de su elección. Cada estructura debe tener una explicación de su función precediéndola y un comentario al final indicando su terminación.

    Ejemplo de comentarios de marca de terminación:

    for ( tableIndex = 0; tableIndex < tableCount; tableIndex++ ) {
    
       while ( recordIndex < recordCount ) {
    
          if ( !IllegalRecordNumber( recordIndex ) ) {
    
             ...
    
          } // if
    
       } // while
    
    } // for

    Comentarios de rutinas

    Las rutinas se deben comentar siempre. No se deben hacer grandes headers con mucha información, los que a veces son más largos que el mismo código. Un buen comentario de rutinas contiene los elementos mencionados en la sección 6 en template para módulos. No es necesario usar siempre todos los campos, sólo se usan si son necesarios.

    Comentarios de files, classes y programas

    Las clases, los files y los programas se caracterizan por tener múltiples rutinas. Siempre, las rutinas agrupadas, deben tener una relación estrecha. Esto es lo que se debe documentar, un resumen del contenido de las rutinas. Una forma fácil para hacerlo es pensar en el motivo por el que se pusieron juntas. Para buenos comentarios siga la guía de los templates en la sección 6.

  6. CODIGO AUTODOCUMENTADO

  7. Se ha propuesto que la mejor solución al problema de documentación es usar lenguajes autodocumentados.”[2] Desde la aparición de los lenguajes de alto nivel es posible escribir nombres de rutinas, datos, estructuras, clases y archivos entendibles para seres humanos. Usar nombres sencillos y descriptivos hace la lectura del código mucho más fácil.

    Los comentarios deben ser sólo una herramienta para decir lo que no se puede decir en el código. Los lenguajes de programación son eso mismo, lenguajes, expresan instrucciones a seguir. Si alguien conoce el lenguaje, debe ser capaz de entender lo que dice, por lo tanto no es necesario decírselo en otro lenguaje. Debemos decirle en otro lenguaje, solamente lo que no puede entender si lee sólo el código. En el libro hemos aprendido como escribir nuestro código para que otros lo entiendan, ésta es la mejor solución para que otros disfruten la lectura de nuestros programas.

    Ejemplo:

    Código mal escrito:

    for ( i = 2; i <= num; i++ ) {
    
    meetsCriteria[ i ] = true;
    
    }
    
    for ( i = 2; i <= num / 2; i++ ) {
    
    j = i + i;
    
    while ( j <= num ) {
    
    meetsCriteria[ j ] = false;
    
    j = j + i;
    
    }
    
    }
    
    for ( i = 1; i <= num; i++ ) {
    
    if ( meetsCriteria[ i ] ) {
    
    System.out.println ( i + " meets criteria." );
    
    }
    
    }

    Código bien escrito:

    for ( primeCandidate = 2; primeCandidate <= num; primeCandidate++ ) {
    
       isPrime[ primeCandidate ] = true;
    
    }for ( int factor = 2; factor < ( num / 2 ); factor++ ) {
    
        int factorableNumber = factor + factor;
    
        while ( factorableNumber <= num ) {
    
            isPrime[ factorableNumber ] = false;
    
            factorableNumber = factorableNumber + factor;
    
        }
    
    }
    
    for ( primeCandidate = 1; primeCandidate <= num; primeCandidate++ ) {
    
       if ( isPrime[ primeCandidate ] ) {
    
          System.out.println( primeCandidate + " is prime." );
    
       }
    
    }
  8. USO DE PSEUDOCODIGO

  9. El pseudocódigo trae muchas ventajas a la hora de programar. Primero que todo, es una herramienta útil para diseñar rutinas y clases. Escribir el pseudocódigo hace que el programador piense bien lo que quiere lograr y permite que cada línea de código que se escriba tenga un propósito específico y conocido, uno que el programador tiene bien claro; tanto que es capaz de escribirlo en su idioma. Además de esto, a la hora de terminar el código, los comentarios ya están ahí. Tenga en cuenta que la parte del pseudocódigo que dice exactamente lo que hace el código es reemplazada por éste, no se deja, ya que no agregaría nada útil al mismo.

  10. USO DE TEMPLATES

    Para documentar rutinas, clases y archivos es posible utilizar guías para saber qué es lo que debemos escribir. A continuación hay varios ejemplos de templates para documentación:

    Template para módulos:

    • Propósito del módulo (una o dos oraciones).

    • Fecha de revisión.

    • Limitaciones y restricciones del algoritmo usado.

    • Descripción de datos de entrada y salida.

    • Suposiciones que deben ser tomadas en cuenta.

    • Tipos de errores y procedimientos de recuperación.

    • Efectos globales de la rutina.

    Template para clases:

    • Descripción del diseño utilizado.

    • Limitaciones y suposiciones.

    • Descripción de la interface para el usuario.

    Template para files:

    • Propósito y contenido del file.

    • Nombre, email y teléfono del autor.

    • Control de versiones.

    • Noticias legales y políticas de uso.

  11. Nota: cada elemento del template se debe usar sólo si es necesario para la rutina. Por ejemplo, no debe describir errores, si no hay errores en esa rutina.

  12. REFERENCIAS

  1. McConnell, S. Code Complete, Microsoft Press, 2004.

  2. Martin, J., McClure, C. Software Maintenance: The Problem and its Solutions, Prentice-Hall, 1983.

  3. Marca, D., Applying Software Engineering Principles, Little Brown and Company, 1984.

  4. King, D. Current Practices in Software Development, Yourdon Press, 1984.

  5. Aron, J. D. The Program Development Process, Addison-Wesley, 1974.

Tamaños de los diferentes tipos de identificadores (variables) en C y C++ September 20, 2007

Posted by karlsauter in Programación I.
1 comment so far

Los tamaños de cada tipo en C y C++ no son siempre iguales. Estos tamaños, no sólo dependen de la arquitectura de la computadora en la que se esté compilando, sino del compilador usado y a veces hasta del sistema operativo en el que se está compilando.

 

Esto es algo que afecta la portabilidad del lenguaje ya que puede producir errores en el código cuando se compila en diferentes entornos. A pesar de esto si hay un mínimo en el tamaño de cada tipo, que, sin importar el entorno, siempre va a ser igual. Estos son:

 

char——————-8 bits

short int————–16 bits

int———————16 bits

long int—————32 bits

float——————-32 bits

double—————-64 bits

long double———-64 bits

 

Estos tamaños son el mínimo aceptado para cada tipo, pero pueden variar con el compilador, el sistema operativo y la arquitectura. Algunas herramientas que ayudan al manejo de tipos son el include <stdint.c> que permite especificar el tamaño de int que se quiere usar y el ‘AC_CHECK_SIZEOF’ macro por GNU, que permite especificar los tamaños por medio de typedef.

Permutaciones September 20, 2007

Posted by karlsauter in Programación I.
add a comment
  1. INTRODUCTION

  2. Una permutación es un arreglo (lista) de objetos en un orden específico. Un arreglo de n elementos puede tener diversas permutaciones, cada permutación se distingue de otra por el lugar que ocupan los elementos en esta. Por ejemplo en el arreglo [n] = {1, 2, 3, …, n}, el 1 ocupa el primer lugar, el 2 el segundo y así sucesivamente hasta llegar a n. En cambio la siguiente es una permutación distinta que la anterior ya que el 2 ocupa la primera posición y el 1 la segunda [n] = {2, 1, 3, …, n}.

  3. FACTORIAL Y PERMUTACIONES

  4. Factorial

    El factorial es una operación matemática denotada por n!. Donde n! = n(n-1)(n-2)…(2)(1). Eso signifca que 3! = 3(2)(1) = 6. La única permutación que no se puede definir así es la de 0 que es 0! = 1.

    Cantidad de permutaciones diferentes

    La cantidad de permutaciones de un número n de elementos es igual a n!. Eso significa que la cantidad de permutaciones diferentes de un arreglo de 4 elementos es igual a 4! = 24.

  5. NOTACION

  6. Hay diferentes formas de notación para expresar permutaciones indicando los cambios que se realizan a un primer arreglo de elementos. Sólo presento tres, esto no implica que no haya mas.

    Lista de Inversiones

    En una lista de inversiones (a1, …, an) ai representa el número de elementos mayores que i que están a la izquierda de i. Por ejemplo la siguiente lista de inversiones (2 3 6 4 0 2 2 1 0) construye la permutacón de (5 9 1 8 2 6 4 7 3) de la siguiente manera: Empezamos con el 9. Luego como a8 dice 1 escribimos 9 8. El siguiente dice 2 por lo tanto es 9 8 7. El elemento a6 dice 2, por lo que el 6 sólo tiene 2 elementos a su izquierda, entonces 9 8 6 7. Y así sucesivamente hasta llegar a (5 9 1 8 2 6 4 7 3).

    Ciclos

    Los ciclos representan los números que cambian unos con otros, formando al final ciclos de cambios. Como ejemplo representaremos una permutación del siguiente arreglo (1 2 3 4). Si el ciclo es (2 3 4) (1) eso implica que el uno no cambia con nadie, el dos cambia con el tres, el tres con el cuatro y el cuatro con el dos. Des esta manera nuestro arreglo queda ( 1 4 2 3).

    Matriz

    La matriz simplemente representa en una matriz de 2 x n los arreglos en su orden antiguo y nuevo.
    Ej:

    1 2 3
    2 1 3
  7. ORDEN

  8. Lexicográfico

    El orden lexicográfico es el orden en el que más fácil pensamos cuando vemos permutaciones y queremos organizarlas. En este orden los número cambian de posiciones de dos en dos cada vez. Todas las combinaciones con el primer valor aparecen primero, luego el segundo valor, luego el tercero, el cuarto y asi sucesivamente hasta n. Igual pasa con las permutaciones dentro de ella. Los elementos en una posición menor siempre se quedan ahí hasta que se realizan todas las permutaciones con los elementos en una posición mayor que ellos. Ej: (1 2 3), (1 3 2), (2 1 3), (2 3 1), (3 1 2), ( 3 2 1)

    De transposición

    Es un orden en el que cada permutación siguiente difiere de la anterior por la transposición de dos elementos adyacentes. Hay diferentes formas de lograr este orden. Por eso un mismo arreglo puede tener diferentes ordenes de transposición. Por ejemplo: 123, 132, 312, 321, 231, 213

  9. REFERENCIAS

  1. ACM, Collected Algorithms from ACM, 71, 86, 102, 202

  2. Knuth, Donald, Fundamental Algorithms

  3. Skiena, Steve S., The algorithm Design Manual

  4. Oosterwal, Erik, All Permutations Routine, http://www.geocities.com/oosterwal/computer/combinations.html

  5. Recombining Permutations,

    http://www.cut-the-knot.org/Curriculum/Combinatorics/PermOnCircle.shtml

  6. Permutation, http://mathworld.wolfram.com

  7. Finite-Geometry Models,

    http://www.cut-the-knot.org/do_you_know/permutation.shtml#permutation

Análisis y Diseño May 19, 2007

Posted by karlsauter in Análisis y Diseño I.
add a comment

Esta es una de las fases del ciclo de vida de un software. Según la Política del Ciclo de Vida del Desarrollo de Sistemas del U.S. House of Representatives, esta fase es “[...] un paso complejo y crítico para determinar cual diseño de sistema, basado en ingeniería de sistemas y análisis tecnológico, cumple con los requerimientos del usuario y el sistema” [4].

El análisis es uno de los pasos más importantes ya que consiste en obtener los requerimientos y necesidades del usuario, sin los cuales no se puede presentar un sistema que sea útil para aquel que lo solicita. Wikipedia dice que los usuarios usualmente saben lo que quieren, pero no lo que el software debe hacer. Durante el análisis se estudia el sistema dividiéndolo en partes (funciones, componentes u objetos) para entender como se relacionan, y luego entender el sistema como un todo.

La IEEE define el diseño como “1) [...] el proceso de definir la arquitectura, componentes, interfaces, y otras características de un sistema o componente 2) Las características de un sistema o software que son seleccionadas por un desarrollador para cumplir con los requerimientos” [2] obtenidos en el análisis.

Modelo de Datos May 19, 2007

Posted by karlsauter in Análisis y Diseño I.
add a comment

La IEEE lo define como “[...] una abstracción del mundo real que incorpora solo aquellas propiedades del entorno a modelar que son relevantes para la aplicación que se desea desarrollar. Normalmente define un grupo de entidades, sus atributos y las relaciones entre ellos. Es independiente de un sistema de computadora y de sus estructuras de datos asociadas” [2]. El modelo de datos toma un problema o una situación de la realidad para la cual se desea desarrollar una aplicación y la representa por medio de un modelo para entender de mejor forma los elementos que la componen, las características de estos que son relevantes para el desarrollo y operación de la aplicación y las relaciones entre ellos.

Existen esencialmente dos estilos de modelo de datos: lógicos y físicos. Los lógicos describen a través de símbolos las entidades, sus atributos y las relaciones entre ellos; mientras que los físicos se usan para diseñar el esquema interno de una base de datos, usando tablas, las columnas que éstas van a tener y las relaciones entre las tablas.

Los pasos para modelar una realidad son:

  • Identificar entidades.

  • Identificar atributos.

  • Identificar relaciones.

  • Aplicar patrones de modelos de datos.

  • Asignar llaves.

  • Normalizar para reducir redundancia de datos.

  • Denormalizar para mejorar el desempeño.

El modelo más usado es el relacional que asume que todos los datos son representados por medio de relaciones matemáticas. Esto permite que las relaciones sean expresadas mediante tablas y relaciones entre ellas. Otro modelo es el entidad relación o ER. Por medio de éste los datos se representan haciendo uso de entidades y sus características. Normalmente se comienza con este sistema u otro y luego se pasa al relacional para poder implementar la base de datos en una computadora.

Ciclo de vida de un software May 19, 2007

Posted by karlsauter in Análisis y Diseño I.
1 comment so far

El ciclo de vida es un proceso de varias etapas que comienza con la necesidad de un usuario o cliente, produce un software que satisface esa necesidad y termina con el desecho de la aplicación. El proceso se lleva a cabo mediante varias etapas. Usualmente estas etapas son:

  • Planificación:

  • Análisis:

  • Diseño.

  • Implementación.

  • Prueba.

  • Instalación.

  • Mantenimiento.

Algunos autores presentan más y otros menos, otros usan nombres diferentes, pero todos siguen la misma línea. Estas etapas se pueden llevar a cabo de diferentes maneras. Pueden ser llevadas a cabo de diferentes maneras. Depende del problema que se esté enfrentando podemos elegir uno de los siguientes modelos para trabajar:

  • Cascada.

  • Espiral.

  • Evolutivo.

  • Formal.

  • Iterativo.

El modelo de cascada es, en mi opinión, el más limitante al momento de trabajar. Requiere mucho tiempo y hace que el proyecto se detenga en momentos de falta de información o de ideas, pero permite la mayor calidad. El modelo consiste en no comenzar ninguna etapa hasta que la anterior no sea completada totalmente. Con este método de trabajo es difícil comenzar a trabajar, ya que las ideas tienen que estar totalmente claras, las necesidades del cliente tienen que estar descritas con mucha exactitud y el programador o el equipo debe estar seguro de como va a trabajar y exactamente qué y cómo lo va a hacer. A pesar de que esto requiere mucho tiempo, asegura que no habrá que regresar en las etapas a re diseñar ideas que no estaban claras ya que, desde el principio estará claro y seguro lo que hay que hacer.

Ingeniería de Software May 18, 2007

Posted by karlsauter in Análisis y Diseño I.
add a comment

Para empezar es bueno discutir que “no es” la ingeniería de software. No es una disciplina dedicada a la creación de programas. Tampoco trabaja solo con la parte teórica ni solo con sistematización. No es una ciencia y por lo tanto no es capaz de producir resultados ni predicciones exactas y sin errores. Es posible diseñar aplicaciones sin la necesidad de ser un ingeniero y se puede ser muy bueno en análisis de problemas y creación de algoritmos y soluciones computarizadas sin aplicar la ingeniería.

Para definir la ingeniería de software es bueno comenzar definiendo cada término por separado. Según el diccionario de Wikipedia, una ingeniería es la aplicación de la ciencia a las necesidades humanas. El diccionario Vox dice que es la aplicación de la ciencia al comercio o la industria. Por otro lado el Software son los programas escritas en código que le dicen a una computadora que debe hacer con los datos que son suministrados y su documentación respectiva. Así, la ingeniería de software es la aplicación de la ciencia al desarrollo de programas para computadoras.

La definición oficial de la IEEE dice lo siguiente: “la ingeniería de software es la aplicación de un abordaje sistemático, disciplinado y cuantificable al desarrollo, operación y mantenimiento de software” [2]. Como podemos ver, es simplemente una aproximación distinta al software, no solo para crearlo, sino para operarlo y mantenerlo. Esto quiere decir que es la aplicación de procesos científicos, estudiados y documentados para la creación, manipulación o modificación de un software durante su tiempo de vida.

Examen ejercicio 2 March 14, 2006

Posted by karlsauter in Sistemas Operativos.
add a comment

Resuelva los siguientes algoritmos de Manejo de Procesos y muestre el tiempo promedio en cada caso: (Nota: El cambio de contexto de RR es de 1 milisegundo)

a. FCFS

Tiempo de espera promedio: 57.4
Tiempo de retorno promedio: 82.8

b. SJN

Tiempo de espera promedio: 39
Tiempo de retorno promedio: 64.4

c. SRT

Tiempo de espera promedio: 40
Tiempo de retorno promedio: 65.4

d. Round Robin

Tiempo de espera promedio: 68.6
Tiempo de retorno promedio: 102.8

Examen ejercicio 1 March 14, 2006

Posted by karlsauter in Sistemas Operativos.
add a comment

Dada la siguiente tabla de páginas en memoria resuelva y calcule los fallos de página para satisfacer la demanda requerida asumiendo un Frame de 2 páginas:

ABDEAEDACDEACBDE

a. FIFO

Fallos: 13/16 = 81.25%
Exitos: 3/16 = 18.75%

a. LRU

Fallos: 12/16 = 75%
Exitos: 4/16 = 25%

b. MRU

Fallos: 13/16 = 81.25%
Exitos: 3/16 = 18.75%

c. LFU

Fallos: 15/16 = 93.75%
Exitos: 1/16 = 6.25%

Ejercicios capitulo 4 February 20, 2006

Posted by karlsauter in Sistemas Operativos.
8 comments

5. El diagrama que sigue (adaptado de Madnick & Donovan, 1974) es un modelo de procesos simplificado de usted, en el cual solamente hay dos estados: durmiendo y despierto.

Usted efectúa la transición de despierto a durmiendo cuando está cansado, y de durmiendo a despierto cuando suena el despertador.
a) Agregue tres estados adicionales al diagrama (por ejemplo, uno podría ser comer).
Comiendo
Haciendo tareas
Jugando
b) Enuncie todas las transiciones posibles entre los cinco estados.
De durmiendo a: despierto.
De comiendo a: haciendo tareas, durmiendo y jugando.
De haciendo tareas a: comiendo, durmiendo y jugando.
De jugando a: comiendo, haciendo tareas y durmiendo.
De despierto a: durmiendo.

6. ¿Cuál es la relación entre el tiempo de retomo, tiempo de ciclo CPU y tiempo de espera? Escriba, si es posible, una ecuación para expresar esta relación.
El tiempo de retorno es igual a la suma del tiempo de ciclo CPU y el tiempo de espera.
Tiempo de retorno = tiempo de ciclo CPU + tiempo de espera

7. Dada la información siguiente:

Dibuje una línea de tiempo para cada uno de los siguientes algoritmos de planificación (pudiera resultar útil calcular primero un tiempo de inicio y de terminación para cada tarea)
a) FCFS

b) SJN

c) SRT

d) Round robin (con un quantum de tiempo de 2, ignore el cambio por contexto y las esperas
naturales)

8. Con la información del ejercicio 3, complete el diagrama calculando el tiempo de espera y el tiempo de retomo para cada uno de los trabajos de los siguientes algo­ritmos de programación (ignore la carga general por cambio por contexto)
a) FCFS
b) SJN
c) SRT
d) Round robin (con un tiempo de quantum de 2)

9. Use la información del ejercicio 3 a fin de calcular el tiempo de espera promedio y el tiempo de retomo promedio para cada uno de los algoritmos de programación que siguen e indique cuál da los mejores resultados.
a) FCFS
Tiempo de espera promedio = (0 + 10 + 12 + 15 + 16) / 5 = 10.6
Tiempo de retorno promedio = (10 + 12 + 15 + 16 + 21) / 5 = 14.8
b) SJN
Tiempo de espera promedio = (11 + 1 + 3 + 0 + 6) / 5 = 4.2
Tiempo de retorno promedio = (21 + 3 + 6 + 1 + 11) / 5 = 8.4
c) SRT
Tiempo de espera promedio = (11 + 1 + 4 + 4 + 7) / 5 = 5.4
Tiempo de retorno promedio = (21 + 3 + 7 + 5 + 12) / 5 = 9.6
d) Round robin (con un quantum de tiempo de 2)
Tiempo de espera promedio = (11 + 2 + 9 + 6 + 10) / 5 = 7.6
Tiempo de retorno promedio = (221+4+12+7+15) /5 = 11.8
El mejor resultado lo obtuvo el algoritmo SJN (Shortest Job Now) con un tiempo de espera promedio de 4.2 y un tiempo de retorno promedio de 8.4; ambos los más bajos.