Decisionescomputo.fismat.umich.mx/computacion/computacion1/actividades/decision... · 1. Planeaci...

22
Decisiones H. Tejeda Febrero 2016 ´ Indice 1. Planeaci´ on de la l´ogica de decisi´ on 2 2. Decisiones con if e if...else 3 3. Sentencias m´ ultiples con if e if...else 6 4. Anidamiento de sentencias if e if...else 8 5. Operadores l´ogicos 9 6. Decisiones eficientes y precisas 11 7. Sentencia switch 15 8. Operador condicional y de negaci´ on 18 9. Precedencia de operadores 20 10.Decisiones en constructores 21 1

Transcript of Decisionescomputo.fismat.umich.mx/computacion/computacion1/actividades/decision... · 1. Planeaci...

Page 1: Decisionescomputo.fismat.umich.mx/computacion/computacion1/actividades/decision... · 1. Planeaci on de la l ogica de decisi on Los programadores generalmente planean las partes complejas

Decisiones

H. Tejeda

Febrero 2016

Indice

1. Planeacion de la logica de decision 2

2. Decisiones con if e if...else 3

3. Sentencias multiples con if e if...else 6

4. Anidamiento de sentencias if e if...else 8

5. Operadores logicos 9

6. Decisiones eficientes y precisas 11

7. Sentencia switch 15

8. Operador condicional y de negacion 18

9. Precedencia de operadores 20

10.Decisiones en constructores 21

1

Page 2: Decisionescomputo.fismat.umich.mx/computacion/computacion1/actividades/decision... · 1. Planeaci on de la l ogica de decisi on Los programadores generalmente planean las partes complejas

1. Planeacion de la logica de decision

Los programadores generalmente planean las partes complejas de los programas con lapizy papel. Estos usan frecuentemente pseudocodigo, una herramienta que ayuda a planearla logica del programa escribiendo sentencias en lenguaje coloquial. El uso de pseudocodigorequiere que se anoten los pasos necesarios para lograr una tarea dada. Alguna tarea que sede en pseudocodigo no tiene que estar relacionada con la computadora. Por ejemplo, escribirlos pasos para llegar a un cierto lugar. Un diagrama de flujo es parecido a un pseudocodigo,pero los pasos se dan en forma de diagrama, como un conjunto de figuras conectadas porflechas.

Se pueden dibujar diagramas de flujo que representen situaciones muy complejas usandosolo rectangulos y rombos. Se usa un rectangulo para representar un paso no condicionadoy un rombo para representar cualquier decision. La estructura logica llamada estructurasecuencial es aquella en la cual un paso sigue a otro sin ninguna condicion. La cantidad depasos es arbitrario.

Los pasos logicos en ocasiones no siguen una secuencia incondicional—las tareas podrıan o noocurrir de acuerdo a las decisiones hechas. Para representar una decision se usa un rombo paratener una pregunta, y se dibujan trayectorias alternativas a los rumbos de accion saliendodel rombo.

La figura 1 incluye dos estructuras de decision, las cuales involucran escoger entre ca-minos alternativos de accion de acuerdo al dıa de la semana. Realizar decisiones es lo quehace que los programas de computo parezcan “inteligentes”.

Figura 1: Diagrama de flujo con decisiones

Todas las decisiones computacionales son decisiones si o no, es decir, la respuesta a cadapregunta computacional es true o false (o on u off ). La razon de lo anterior es porque lacircuiterıa computacional consiste de millones de minusculos interruptores que estan apaga-

2

Page 3: Decisionescomputo.fismat.umich.mx/computacion/computacion1/actividades/decision... · 1. Planeaci on de la l ogica de decisi on Los programadores generalmente planean las partes complejas

dos o encendidos, y el resultado de cada decision se pone en uno de estos interruptores enla memoria. Los valores booleanos (o logicos) son true o false, y cada decision compu-tacional da un valor booleano. Ası un programa pregunta “¿ingreso el usuario un 1?” “sino,¿ingreso el usuario un 2?” “sino, ¿ingreso el usuario un 3?” en vez de una pregunta como“¿Que numero ingreso el usuario?”.

2. Decisiones con if e if...else

La sentencia mas simple en Java que se puede usar para hacer una decision es la sentenciaif. Suponer que se ha declarado una variable entera llamada calificacion y se quieremostrar un mensaje cuando el valor de calificacion es 10. La sentencia if, codigo 1, hacela decision de sı se debe producir salida. Observar que signo doble igual (==) es usado paradeterminar igualdad; este es un operador de equivalencia de Java.

1 i f ( c a l i f i c a c i on == 10)2 System . out . p r i n t l n ( ”La c a l i f i c a c i on es p e r f e c t a ” ) ;

Codigo 1: Ejemplo de una sentencia if.

Si calificacion, en el codigo 1, tiene el valor 10, el valor booleano de la expresion califica-

cion == 10 es true, y la subsecuente sentencia de salida se ejecuta. Si el valor de la expresiones false, porque calificacion tiene un valor diferente a 10, la sentencia de salida no seejecuta.

Una sentencia if siempre requiere parentesis. Dentro de los parentesis, se puede colocarcualquier expresion booleana, las cuales usan alguno de los siguientes operadores relacionales:==, ! =, <, >, <=, >=. Sin embargo, se puede usar cualquier expresion que de un valorbooleano, como una variable booleana, o una llamada a un metodo.

2.1. Colocacion incorrecta de punto y coma en sentencia if

En el codigo 1 no hay un punto y coma al final de la primera lınea de la sentencia if ya quela sentencia no termina ahı. La sentencia termina despues de la llamada a println(), poreso es donde se pone el punto y coma. Se podrıa intentar poner la sentencia if entera enuna sola lınea y se ejecutarıa correctamente; sin embargo, el formato de dos lıneas para lasentencia if es mas convencional y facil de leer, ası que se pone la sentencia if y la expresionbooleana en una lınea, y se sangra con espacios antes de codificar la accion que ocurre si laexpresion booleana se evalua como true. Ser cuidadoso—si se usa el formato de dos lıneasy se pone un punto y coma al final de la primera lınea, como se muestra en el ejemplo delcodigo 2, da un resultado que podrıa no ser el que se intenta.

3

Page 4: Decisionescomputo.fismat.umich.mx/computacion/computacion1/actividades/decision... · 1. Planeaci on de la l ogica de decisi on Los programadores generalmente planean las partes complejas

1 i f ( c a l i f i c a c i on == 1 0 ) ;2 System . out . p r i n t l n ( ”La c a l i f i c a c i on es p e r f e c t a ” ) ;

Codigo 2: Colocacion extra de ; despues de la expresion booleana en la sentencia if.

Cuando la expresion booleana en el codigo 2 es true, una sentencia vacıa contenida entrela expresion booleana y el punto y coma se ejecuta. Si la expresion probada se evalua a true

o false, la decision es inmediata (no hacer nada), y la ejecucion continua con la siguientesentencia independientemente para mostrar siempre un mensaje. En este caso, por el puntoy coma incorrecto, la sentencia if no hace nada.

2.2. Operador de asignacion en vez de equivalencia

Otro error de programacion comun es cuando el programador usar un solo signo de igualen vez de un doble signo de igual cuando intenta determinar la igualdad. La expresioncalificacion = 10 no hace la comparacion de calificacion con 10, lo que intenta haceres una asignacion de 10 a calificacion. Si se usa esta asignacion en la sentencia if, estaes ilegal porque solo expresiones booleanas son permitidas.

Nota. La expresion if(x = true) compilara solo si x es una variable booleana, ya que

es legal asignar true a x. Sin embargo, esta sentencia es poco util ya que el valor de la

expresion nunca podrıa ser false.

Una alternativa al uso de una expresion booleana en una sentencia if, es guardar el valorde la expresion booleana en una variable booleana. Y luego usar la variable en la sentenciaif como se muestra enseguida.

esCalificacionPerfecta = (calificacion == 10);

if ( esCalificacionPerfecta )

System.out.println("La calificacion es perfecta.");

Lo anterior agrega un paso extra al programa, pero hace la sentencia if mas similar a unasentencia del lenguaje coloquial.

2.3. Intentar comparar objetos con operadores relacionales

Para los tipos primitivos, como int y double se pueden usar los operadores relacionalesestandar (==, <,>,<=, >=, y !=). Sin embargo no se pueden usar <,>,<=, o >= paracomparar objetos; un programa con tales comparaciones no compila. Se pueden usar lascomparaciones == y ! = con objetos, pero cuando se usan, no se comparan sus valores,se comparan las direcciones de memoria de los objetos. == dara true para dos objetos

4

Page 5: Decisionescomputo.fismat.umich.mx/computacion/computacion1/actividades/decision... · 1. Planeaci on de la l ogica de decisi on Los programadores generalmente planean las partes complejas

cuando ellos se refieran al mismo objeto en memoria, y no cuando ellos son objetos diferentescon el mismo valor. Para comparar los valores de los objetos, se deberıan escribir metodosespecializados. Por ejemplo, con objetos String no se debe usar ==.

Los nombres de los objetos son referencias, sus nombres de campos no son referencias siellos representan tipos de datos primitivos. Se podrıa comparar los valores entre campos deobjetos usando metodos accesores publicos. Por ejemplo, suponer que se ha creado una clasellamada Estudiante con un campo double para el promedio y un metodo publico llamadogetPromedio(). Despues de instanciar dos objetos, estudiante1 y estudiante2, se puedeescribir una sentencia como la siguiente:

if (estudiante1.getPromedio() > estudiante2.getPromedio())

System.out.println("Primer estudiante con un promedio mayor");

Los valores representados por estudiante1.getPromedio() y estudiante2.getPromedio()

son double, ası que pueden ser comparados usando cualquier operador relacional.

2.4. Estructura if...else

En la siguiente sentencia:

if (calificacion == 10)

System.out.println("La calificacion es perfecta");

Esta sentencia tambien es llamada una alternativa simple if porque el programa solorealiza una accion, o no, basada en una alternativa. En ocasiones se requieren dos opcionespara el camino de la accion siguiendo a la decision. Una alternativa doble if es la estructurade decision que se usa cuando se necesita tomar uno u otro de dos posibles caminos de accion.En Java, la sentencia if...else da el mecanismo para realizar una accion cuando unaexpresion booleana evalua a true y para realizar una accion diferente cuando la expresionbooleana evalua a false.

El codigo 3 muestra uno de dos mensajes. Cuando el valor de calificacion es 10, la clausu-la if de la sentencia es ejecutada, mostrando el mensaje “La calificacion es perfecta”. Cuandocalificacion es cualquier valor diferente de 10, la clausula else de la sentencia se ejecutay el programa muestra el mensaje “No lo es”. Se puede codificar un if sin un else, pero esilegal codificar un else si un if que le preceda.

1 i f ( c a l i f i c a c i on == 1 0 ) ;2 System . out . p r i n t l n ( ”La c a l i f i c a c i on es p e r f e c t a ” ) ;3 else4 System . out . p r i n t l n ( ”No l o es ” ) ;

Codigo 3: Una estructura if...else.

5

Page 6: Decisionescomputo.fismat.umich.mx/computacion/computacion1/actividades/decision... · 1. Planeaci on de la l ogica de decisi on Los programadores generalmente planean las partes complejas

El sangrado mostrado en el codigo 3 no es requerido pero es de uso estandar. Se alineanverticalmente las palabras reservadas if y else, y se sangran las sentencias de accion quedependen de la evaluacion.

Cada sentencia, la que sigue al if y la que sigue al else, es una sentencia completa, por loque cada una termina con punto y coma.

3. Sentencias multiples con if e if...else

En ocasiones se quiere ejecutar mas de una accion despues de la evaluacion de una expresionbooleana dentro de una sentencia if. Para ejecutar mas de una sentencia se deben usar llavespara poner las sentencias en un bloque. El siguiente segmento de un programa determina siun empleado ha trabajado mas que el valor de la constante SEMANA COMPLETA; sı ası es, secalcula el pago ordinario y el extraordinario.

if (horasTrabajadas > SEMANA_COMPLETA) {pagoOrdinario = SEMANA_COMPLETA * tarifa;

pagoExtraordinario = (horasTrabajadas - SEMANA_COMPLETA) * TASA_EXTRA *

tarifa;

}

Cuando se pone un bloque dentro de una sentencia if, es importante colocar las llaves co-rrectamente. En el siguiente codigo las llaves fueron omitidas y cuando horasTrabajadas

>SEMANA COMPLETA es true, entonces pagoOrdinario es calculado y la expresion if termi-na. La siguiente sentencia, la que calcula el pago extraordinario, se ejecuta siempre que seejecuta el programa, no importando el valor de horasTrabajadas, es decir, no depende dela sentencia if. El sangrado podrıa ser enganoso; pareciera que las dos sentencias dependendel if, pero el sangrado no hace que esas sentencias sean dependientes del if.

if (horasTrabajadas > SEMANA_COMPLETA)

pagoOrdinario = SEMANA_COMPLETA * tarifa;

pagoExtraordinario = (horasTrabajadas - SEMANA_COMPLETA) * TASA_EXTRA *

tarifa;

Cuando se crea un bloque, no se requiere poner mas de una sentencia. Es legal poner llavesalrededor de una sola sentencia. Por claridad, algunos programadores siempre usan llavespara encerrar las acciones en una sentencia if, no importando sı solo tiene una sentencia elbloque.

Cuando no se hace un bloque de sentencias porque dependen de un if, y se usa la clausulaelse, el programa no compilara. Considerar el siguiente codigo:

6

Page 7: Decisionescomputo.fismat.umich.mx/computacion/computacion1/actividades/decision... · 1. Planeaci on de la l ogica de decisi on Los programadores generalmente planean las partes complejas

if (horasTrabajadas > SEMANA_COMPLETA)

pagoOrdinario = SEMANA_COMPLETA * tarifa;

pagoExtraordinario = (horasTrabajadas - SEMANA_COMPLETA) * TASA_EXTRA *

tarifa;

else

pagoOrdinario = SEMANA_COMPLETA * tarifa;

En este caso, la sentencia if termina despues del primer calculo de pagoOrdinario, y lasegunda sentencia independiente realiza el calculo para pagoExtraordinario. La tercerasentencia inicia con else, la cual es ilegal, ya que hay un else sin un if, es decir la sentenciaprecedente no fue un if que es lo que se requerıa.

Al igual como se pueden hacer bloques de sentencias para que dependan de un if, tambiense puede hacer para un else. La aplicacion Nomina, codigo 4, muestra una estructura if

con dos sentencias dependientes y una else tambien con dos sentencias. La ultima sentenciaprintln() se ejecuta sin importar el valor de la variable horasTrabajadas; no es parte dela estructura if.

1 import java . u t i l . Scanner ;2 public class Nomina {3 public stat ic void main ( St r ing [ ] a rgs ) {4 double t a r i f a ;5 double horasTrabajadas ;6 double pagoOrdinar io ;7 double pagoExtraord inar io ;8 f ina l int SEMANA COMPLETA = 40 ;9 f ina l double TASA EXTRA = 1 . 5 ;

10 Scanner entrada = new Scanner ( System . in ) ;11 System . out . p r i n t ( ”¿Cuantas horas t r a b a j a s t e e s ta semana? ” ) ;12 horasTrabajadas = entrada . nextDouble ( ) ;13 System . out . p r i n t ( ”¿Cua l e s l a t a r i f a ? ” ) ;14 t a r i f a = entrada . nextDouble ( ) ;15 i f ( horasTrabajadas > SEMANA COMPLETA ) {16 pagoOrdinar io = SEMANA COMPLETA ∗ t a r i f a ;17 pagoExtraord inar io = ( horasTrabajadas − SEMANA COMPLETA) ∗18 TASA EXTRA ∗ t a r i f a ;19 }20 else {21 pagoOrdinar io = horasTrabajadas ∗ t a r i f a ;22 pagoExtraord inar io = 0 . 0 ;23 }24 System . out . p r i n t l n ( ”El pago o r d i n a r i o es ” + pagoOrdinar io +25 ”\n El pago extra es ” + pagoExtra ) ;26 }27 }

Codigo 4: Aplicacion interactiva Nomina.

7

Page 8: Decisionescomputo.fismat.umich.mx/computacion/computacion1/actividades/decision... · 1. Planeaci on de la l ogica de decisi on Los programadores generalmente planean las partes complejas

Cuando se hacen bloques de sentencias, se debe recordar que cualquier variable declaradadentro del bloque es local a ese bloque. En el siguiente segmento de codigo se tiene unavariable llamada suma que es local al bloque que sigue al if. La ultima sentencia println()

causa un error porque la variable suma esta fuera de alcance.

if (a == b) {int suma = a + b;

System.out.println("Las dos variables son iguales");

}System.out.println("La suma es " + suma);

4. Anidamiento de sentencias if e if...else

Dentro de una clausula if o else se pueden codificar muchas sentencias dependientes segunse requiera, incluso otras estructuras if. Las estructuras if que estan contenidas dentro deotras if son llamadas sentencias if anidadas. Estas son empleadas cuando dos condicionesdeben ser cumplidas antes de que una accion sea tomada.

Suponer que se quiere pagar un bono de $1,000 a un vendedor solo si este vendio al menostres artıculos que totalicen al menos $20,000 en valor durante un cierto tiempo. El siguientecodigo muestra la solucion al problema.

final int MIN_ARTS = 3;

final int MIN_VENTA = 20000;

final int BONO_VENTA = 1000;

in t bono = 0;

if (articulosVendidos >= MIN_ARTS)

if (totalVenta >= MIN_VENTA)

bono = BONO_VENTA;

Observar que no hay puntos y comas en la sentencia if hasta despues de la sentencia bono

= BONO VENTA. La expresion articulosVendidos >= MIN ARTS es evaluada primero. Solo siesta expresion es true el programa evalua la segunda expresion booleana, totalVenta >=

MIN VENTA. Si esta expresion tambien es true, la sentencia de asignacion del bono se ejecuta,y la estructura if termina.

Cuando se anidan sentencias if se debe tener cuidado al colocar cualquier clausula else.Por ejemplo, suponer que se quieren distribuir bonos con la siguiente polıtica. Si el vendedorno vende al menos tres artıculos, se le dan $200 de bono. Si el vendedor vende al menostres artıculos cuyo valor combinado es menor que $20,000, el bono es de $500. Si el vendedorvende al menos tres artıculos cuyo valor combinado es al menos $20,000 el bono es de $1,000.El siguiente codigo muestra la logica.

8

Page 9: Decisionescomputo.fismat.umich.mx/computacion/computacion1/actividades/decision... · 1. Planeaci on de la l ogica de decisi on Los programadores generalmente planean las partes complejas

final int MIN_ARTS = 3;

final int MIN_VENTA = 20000;

final int BONO_MAYOR = 1000;

final int BONO_MEDIO = 500;

final int BONO_PEQUE~NO = 200;

int bono = 0;

if (articulosVendidos >= MIN_ARTS)

if (totalVenta >= MIN_VENTA)

bono = BONO_MAYOR;

else

bono = BONO_MEDIO;

else

bono = BONO_PEQUE~NO;

Como se muestra en el codigo previo, cuando una sentencia if sigue a otra, la primer clausulaelse encontrada es emparejada con el if mas reciente encontrado. No importa cuantosniveles de sentencias if...else sean requeridos para dar una solucion, las sentencias else

son siempre asociados con los if basados en “primero en entrar, ultimo en salir”. El sangradode las lıneas de codigo ayuda a mostrar cual sentencia else es emparejada con cual sentenciaif.

5. Operadores logicos

Se pueden combinar dos pruebas booleanas en Java en una sola expresion usando los opera-dores logicos Y y O.

5.1. Operador Y

Como alternativa para algunas sentencias if anidadas, se puede usar el operador logico Yentre dos expresiones booleanas para realizar una accion cuando ambas sean true. El ope-rador Y en Java es escrito usando dos ampersands (&&). Las dos sentencias que se muestranenseguida trabajan en la misma forma. En ambos casos, la variable articulosVendidos

debera ser al menos el numero mınimo de artıculos requeridos para un bono y la variabletotalVenta debera ser al menos el valor mınimo requerido para que bono sea puesto aBONO VENTA.

if (articulosVendidos >= MIN_ARTS)

if (totalVenta >= MIN_VENTA)

bono = BONO_VENTA;

9

Page 10: Decisionescomputo.fismat.umich.mx/computacion/computacion1/actividades/decision... · 1. Planeaci on de la l ogica de decisi on Los programadores generalmente planean las partes complejas

if (articulosVendidos >= MIN_ARTS && totalVenta >= MIN_VENTA)

bono = BONO_VENTA;

Cuando se usa el operador && se debe incluir una expresion booleana completa de cada lado,ya que es un operador binario. Si se quiere poner un bono a $8,000 cuando cantidadVendida

esta por encima de $20,000 y por debajo de $100,000, la sentencia correcta es:

if (cantidadVendida > 20000 && cantidadVendida < 100000)

bono = 8000;

La siguiente sentencia no compilara porque no tiene una expresion booleana a cada lado deloperador &&.

if (cantidadVendida > 20000 && < 100000)

bono = 8000;

Por claridad, varios programadores prefieren encerrar cada expresion booleana, que es partede una expresion booleana compuesta con su propio conjunto de parentesis, como en elsiguiente ejemplo:

if ((cantidadVendida > 20000) && (cantidadVendida < 100000))

bono = 8000;

No es obligatorio usar el operador && porque usando sentencias if anidadas siempre selogra el mismo resultado, pero con el operador && se logra un codigo mas compacto, menossusceptible a errores, y mas facil de entender.

5.2. Operador O

Cuando se quiere que alguna accion ocurra si solo una de dos condiciones es true, se puedeusar sentencias if anidadas, o se puede usar el operador logico O, el cual se indica con|| (tubo).

Suponer que se quiere dar un descuento a cualquier cliente que satisfaga al menos una dedos condiciones—haber comprado un mınimo de artıculos o comprado cualquier cantidadde artıculos tal que totalicen al menos un valor mınimo—se puede escribir el codigo usandoalguna de las siguientes dos formas.

if (articulosComprados >= MIN_ARTS)

tarifaDescuento = DESCUENTO;

10

Page 11: Decisionescomputo.fismat.umich.mx/computacion/computacion1/actividades/decision... · 1. Planeaci on de la l ogica de decisi on Los programadores generalmente planean las partes complejas

else

if (articulosTotal >= VALOR_MIN)

tarifaDescuento = DESCUENTO.

if (articulosComprados >= MIN_ARTS || articulosTotal >= VALOR_MIN)

tarifaDescuento = DESCUENTO;

Al igual que con el operador && no es obligatorio usar el operado || porque usando sentenciasif anidadas se logra el mismo resultado. Sin embargo, usando el operador || se hace el codigomas compacto, menos susceptible a errores, y mas facil de entender.

5.3. Evaluacion cortocircuitada

Las expresiones a cada lado de los operadores && y || son evaluadas tanto como sea nece-sario para determinar si la expresion completa es true o false. Esta capacidad es llamadaevaluacion cortocircuitada. Con el operador && ambas expresiones booleanas deberanser true antes de que la accion pueda ocurrir, si la primera expresion probada es false, lasegunda expresion nunca es evaluada ya que su valor no importa.

Con el operador || solo una de las expresiones booleanas debera ser verdadera para hacerque las sentencias dependientes sean ejecutadas, si el primer operando de || es verdadero,entonces no hay necesidad de evaluar la expresion de la derecha, ya que su valor no importa.

Suponer que se han creado dos metodos que devuelven valores booleanos y se usan lasllamadas a estos metodos en una sentencia if, como se muestra enseguida:

if (metodo1() && metodo2())

System.out.println("Correcto");

Dependiendo de las acciones realizadas dentro de los metodos, podrıa ser importante entenderque en este caso, si metodo1() es falso, entonces el metodo2() no se ejecutara.

6. Decisiones eficientes y precisas

Cuando los programadores deben revisar un rango, en ocasiones introducen codigo incorrectoo ineficiente. Se revisa enseguida como hacer revisiones de rango en forma precisa y eficiente,ademas de usar los operadores logicos && y || apropiadamente.

11

Page 12: Decisionescomputo.fismat.umich.mx/computacion/computacion1/actividades/decision... · 1. Planeaci on de la l ogica de decisi on Los programadores generalmente planean las partes complejas

6.1. Revision precisa de rango

Una revision de rango es una secuencia de sentencias que determinan en cual de variosvalores consecutivos otro valor cae. Considerar el caso en el cual un agente de ventas puederecibir una de tres posibles tasas de comision de acuerdo a sus ventas. Una venta totalizando$20,000 o mas da al agente una comision del 8 %, una venta entre $10,000 y hasta $19,999.99da 6 %, y cualquier otra hasta $9,999.99 o menos da 5 %. Empleando tres sentencias if paraprobar expresiones booleana simples podrıa resultar en alguna asignacion incorrecta de lacomision. Por ejemplo, revisar el siguiente codigo:

final double LIM_SUP = 20000.00;

final double COM_SUP = 0.08;

final double LIM_MED = 10000.00;

final double COM_MED = 0.06;

final double LIM_INF = 9999.99;

final double COM_INF = 0.05;

if (totalVenta >= LIM_SUP)

tasaComision = COM_SUP;

if (totalVenta >= LIM_MED)

tasaComision = COM_MED;

if (totalVenta <= LIM_INF)

tasaComision = COM_INF;

Si totalVenta es $20000 al ejecutarse la primera sentencia if la expresion booleana total-Venta>= LIM SUP evalua a true, ası COM SUP es asignada correctamente a tasaComision. Sin em-bargo, la siguiente expresion del segundo if, totalVenta >= LIM MED, tambien evalua comotrue, ası tasaComision, que habıa sido puesta a COM SUP, es incorrectamente puesta ahoraa COM MED.

Una solucion parcial a lo anterior es usar una sentencia else siguiendo a la primera evaluacioncomo se muestra enseguida:

final double LIM_SUP = 20000.00;

final double COM_SUP = 0.08;

final double LIM_MED = 10000.00;

final double COM_MED = 0.06;

final double LIM_INF = 9999.99;

final double COM_INF = 0.05;

if (totalVenta >= LIM_SUP)

tasaComision = COM_SUP;

else

if (totalVenta >= LIM_MED)

12

Page 13: Decisionescomputo.fismat.umich.mx/computacion/computacion1/actividades/decision... · 1. Planeaci on de la l ogica de decisi on Los programadores generalmente planean las partes complejas

tasaComision = COM_MED;

if (totalVenta <= LIM_INF)

tasaComision = COM_INF;

En este codigo, cuando totalVenta es $20,000, la expresion totalVenta >= LIM SUP estrue y a tasaComision se asigna COM SUP; entonces la estructura entera if termina. CuandototalVenta no es mayor que o igual a $20,000 (por ejemplo, $16,000), la primera expresionif es false, y la sentencia else se ejecuta y pone correctamente tasaComision a COM MED.

Este codigo es algo ineficiente, cuando totalVenta es cualquier cantidad por encima deLIM INF, el primer if pone tasaComision a COM SUP para cantidades que estan al menos en$20,000, o su else pone tasaComision a COM MED para cantidades que estan son al menos$10,000. En cualquiera de estos dos casos, el valor booleano probado en la siguiente sentencia,if(totalVenta <= LIM INF), es siempre false, ası tasaComision retiene su valor correcto.Sin embargo, fue innecesario preguntar por el LIM INF.

Despues de que se sabe que totalVenta no es al menos LIM MED, en vez de preguntarif(totalVenta <= LIM INF), es mas facil, mas eficiente, y menos susceptible a errores usarun else. Si totalVenta no es al menos LIM SUP y tampoco es al menos LIM MED, estedebera ser por defecto al menos que o igual a LIM INF. En el siguiente codigo se muestrala logica mejorada. Observar que la constante LIM INF ya no es mas declarada porque yano se necesita mas—si totalVenta no es mayor que o igual a LIM MED, la tasaComision

debera recibir COM INF.

final double LIM_SUP = 20000.00;

final double COM_SUP = 0.08;

final double LIM_MED = 10000.00;

final double COM_MED = 0.06;

final double COM_INF = 0.05;

if (totalVenta >= LIM_SUP)

tasaComision = COM_SUP;

else

if (totalVenta >= LIM_MED)

tasaComision = COM_MED;

else

tasaComision = COM_INF;

6.2. Revisiones de rango eficientes

Dentro de un if...else anidado, como el del codigo anterior, es mas eficiente hacer lapregunta que sea mas probable que sea verdadera al inicio. Es decir, si se sabe que la mayorıade veces el valor de totalVenta es grande, comparar primero totalVenta con LIM SUP.

13

Page 14: Decisionescomputo.fismat.umich.mx/computacion/computacion1/actividades/decision... · 1. Planeaci on de la l ogica de decisi on Los programadores generalmente planean las partes complejas

De esta forma, es mas frecuente evitar hacer multiples preguntas. Sin embargo, si se sabeque la mayorıa de veces totalVenta es pequeno, se debe preguntar primero if(totalVenta

<LIM INF). El siguiente codigo asigna el mismo valor de comision para cualquier totalVentadado, pero esta secuencia de decisiones es mas eficiente cuando la mayorıa de valores detotalVenta son pequenos.

final double COM_SUP = 0.08;

final double LIM_MED = 10000.00;

final double COM_MED = 0.06;

final double LIM_INF = 5000.00;

final double COM_INF = 0.05;

if (totalVenta < LIM_INF)

tasaComision = COM_INF;

else

if (totalVenta < LIM_MED)

tasaComision = COM_MED;

else

tasaComision = COM_SUP;

Observar que en las comparaciones se usaron los operadores < en vez de <=. Esto es porquecon totalVenta de $20,000 debera dar COM SUP, y con totalVenta de $5,000 da COM MED.Si se querıa usar <=, entonces se debio cambiar los valores de corte de LIM INF y LIM MED

a $4,999.99 y $9,999.99, respectivamente.

6.3. Uso correcto de && y ||

Los programadores novatos frecuentemente usan el operador && cuando quieren usar ||, yviceversa. En ocasiones lo que se pide, se toma literal al programar y eso genera el problemade la logica del codigo. Suponer que alguien pide algo como “mostrar un mensaje de errorcuando el pago por hora de un trabajador este por debajo de $120.00 y cuando este porencima de $1200.00”. Entonces al codificar se escribe algo como:

if (pagoHora < INFERIOR && pago > SUPERIOR)

System.out.println("Error en el pago por hora");

Para una sola variable, el valor de pagoHora no puede estar por debajo $120.00 y por encimade $1,200 simultaneamente, ası que la sentencia de salida nunca se ejecutara, sin importarel valor de pagoHora. Para el proposito del codigo se debe usar el operador || para mostrarel mensaje de error bajo las circunstancias correctas, como se muestra enseguida:

if (pagoHora < INFERIOR || pago > SUPERIOR)

System.out.println("Error en el pago por hora");

14

Page 15: Decisionescomputo.fismat.umich.mx/computacion/computacion1/actividades/decision... · 1. Planeaci on de la l ogica de decisi on Los programadores generalmente planean las partes complejas

De igual forma cuando se pide mostrar los nombres de los empleados en los departamentos1 y 2, no se debe intentar escribir el codigo como se muestra enseguida, ya que el uso de lapalabra y es como conjuncion, no como operador logico:

if (departamento == 1 && departamento == 2)

System.out.println("El nombre es: " + nombre);

Ya que la variable departamento no puede contener un 1 y un 2 al mismo tiempo, ası queno se mostrara el nombre de ningun empleado, no importando el valor de departamento. Lasentencia correcta que escoge empleados cuyo departamento es 1 o 2, es la siguiente:

if (departamento == 1 || departamento == 2)

System.out.println("El nombre es: " + nombre);

Otro tipo de error ocurre si se usa un solo ampersand o un tubo cuando solo se trata deindicar el operador logico Y o O. Se pueden usar con expresiones booleanas, pero ambas sonevaluadas porque el modo cortocircuitada no esta presente. Tambien pueden emplearse pararealizar las operaciones logicas Y y O a nivel bit, cuando se ponen operandos enteros.

7. Sentencia switch

Anidando una serie de sentencias if y else se puede escoger de varias alternativas. Suponerque se quiere mostrar el costo de diferentes tipos de cafe de acuerdo a una seleccion previade un cliente. El siguiente codigo muestra una posible implementacion del programa.

if (opcion == 1)

System.out.println("Cafe americano");

else

if (opcion == 2)

System.out.println("Cafe expresso");

else

if (opcion == 3)

System.out.println("Cafe americano");

else

if (opcion == 4)

System.out.println("Cafe latte");

else

System.out.println("Cafe moca");

Una alternativa al uso de series de sentencias if anidadas es con la sentencia switch. Lasentencia switch es util cuando se necesita probar una sola variable contra una serie deenteros, caracteres, o de cadenas, esto ultimo a partir de Java 7.

15

Page 16: Decisionescomputo.fismat.umich.mx/computacion/computacion1/actividades/decision... · 1. Planeaci on de la l ogica de decisi on Los programadores generalmente planean las partes complejas

La sentencia switch usa cuatro palabras claves:

switch inicia la estructura y es seguida inmediatamente por la expresion de pruebaencerrada en parentesis.

case es seguido por uno de los valores posibles para la prueba de expresion y por dospuntos.

break opcionalmente termina una sentencia switch al final de cada case.

default opcionalmente es usado para cualquier accion que deberıa ocurrir si la variablede prueba no empata ningun caso.

El siguiente codigo muestra la sentencia switch usada para mostrar los diferentes tipos decafe.

switch (opcion) {case 1:

System.out.println("Cafe americano");

break;

case 2:

System.out.println("Cafe expresso");

break;

case 3:

System.out.println("Cafe americano");

break;

case 4:

System.out.println("Cafe latte");

break;

default :

System.out.println("Cafe moca");

}

No se requiere poner los valores del case en orden ascendente, como en el codigo anterior,sin embargo hacerlo de esta forma hace mas facil entender la sentencia. Por eficiencia, sedeberıan poner primero los de mayor probabilidad.

La sentencia switch comienza evaluando la variable opcion mostrada en la primera lınea. Siopcion es igual a 1, la sentencia que muestra “Cafe americano” se ejecuta. La sentencia break

omite el resto de la estructura switch, y la ejecucion continua con la siguiente sentenciadespues de la llave de cierre de la estructura switch.

Si opcion no es igual al valor 1 del primer case, el siguiente valor case es comparado,y ası sucesivamente. Si la variable opcion no contiene el mismo valor que alguno de lassentencias case, las sentencias del default son ejecutadas.

16

Page 17: Decisionescomputo.fismat.umich.mx/computacion/computacion1/actividades/decision... · 1. Planeaci on de la l ogica de decisi on Los programadores generalmente planean las partes complejas

Una estructura switch se puede dejar sin sentencias break. Si el programa aparea la variablede prueba con algun caso, todas las sentencias dentro de la sentencia switch se ejecutan desdeese lugar en adelante. Por ejemplo, si se omiten todas las sentencias en el codigo anterior,cuando opcion es 3, los primeros dos casos son omitidos, pero cafe americano, cafe latte ycafe moca son mostrados. Se podrıa intencionalmente omitir las sentencias break si se quiereque todos los subsecuentes casos se ejecuten despues de que la variable sea apareada.

No se necesita escribir codigo para cada caso en una sentencia switch. Por ejemplo, suponerque el supervisor para los departamentos 1, 2, y 3 es Gomez, pero otros departamentos tienensupervisores diferentes. Es ese caso, se podrıa usar el siguiente codigo.

int departamento;

String supervisor;

// las sentencias para obtener el departamento irıan aquı

switch (departamento) {case 1:

case 2:

case 3:

supervisor = "Gomez";

break;

case 4:

supervisor = "Perez";

break;

case 5:

supervisor = "Hernandez";

break;

default :

System.out.println("Codigo de departamento invalido");

}

Por otra parte, se podrıan usar cadenas en una estructura switch para determinar si unnombre de supervisor es valido, como se muestra en el siguiente metodo.

public static boolean esSupervisorValido(String nombre) {boolean esValido;

switch (nombre) {case "Gomez":

case "Perez":

case "Hernandez":

esValido = true;

break;

default :

esValido = false;

}

17

Page 18: Decisionescomputo.fismat.umich.mx/computacion/computacion1/actividades/decision... · 1. Planeaci on de la l ogica de decisi on Los programadores generalmente planean las partes complejas

return esValido;

}

Cuando una variable char debe ser revisada y se quiere ignorar si son mayusculas o minuscu-las, se puede usar la tecnica de sentencias case vacıas, como se muestra enseguida.

switch (codigoDepartamento) {case ’c’:

case ’C’:

nombreDepartamento = "Contabilidad";

break;

case ’v’:

case ’V’:

nombreDepartamento = "Ventas";

break;

// y ası sucesivamente

}

No se obliga a usar la estructura switch; siempre se puede lograr los mismos resultados consentencias if anidadas. La estructura switch es simple usar cuando hay varios caminos deaccion que dependen de un solo valor entero, caracter, o cadena. Tiene sentido usar switchsolo cuando una cantidad razonable de valores especıficos de apareamiento necesitan serprobados.

8. Operador condicional y de negacion

Ademas de la sentencia if y la estructura switch, Java proporciona otra forma de hacerdecisiones. El operador condicional requiere tres expresiones separadas con un signo deinterrogacion de cierre y dos puntos y es usado como una version abreviada de la estructuraif...else. Nunca se requiere usar el operador condicional, pero es una forma abreviada.La sintaxis del operador condicional es:

expresionPrueba ? resultadoVerdadero : resultadoFalso;

La primera expresion, expresionPrueba, es una expresion booleana. Si esta es true, laexpresion entera condicional toma el valor de la expresion siguiendo al signo de interrogacion(resultadoVerdadero). Si el valor de la expresionPrueba es false, la expresion enteratoma el valor de resultadoFalso.

El operador condicional es un operador ternario—uno que necesita tres operandos. HastaJava 6 este era el unico operador condicional. Desde Java 7 se introdujo la version colapsada

18

Page 19: Decisionescomputo.fismat.umich.mx/computacion/computacion1/actividades/decision... · 1. Planeaci on de la l ogica de decisi on Los programadores generalmente planean las partes complejas

del operador ternario que revisa por valores null asignados a objetos. Este nuevo operadores llamado el operador Elvis porque usa un signo de interrogacion y dos puntos juntos (?:);,si se ve de lado, recuerda a Elvis Presley.

Por ejemplo, suponer que se quiere asignar el precio mas pequeno a un artıculo. Sea lavariable a el precio publicado y la variable b el precio descontado. La expresion para asignarel costo mas pequeno es:

precio = (a < b) ? a : b;

Cuando se evalua la expresion a < b, donde a es menor que b, la expresion condicional enteratoma el valor a la izquierda de los dos puntos, a, el cual es entonces asignado a precio. Sia no es menor que b, la expresion toma el valor de la derecha de los dos puntos, b, y b esasignado a precio.

Se pudo lograr los mismos resultados con la siguiente sentencia if...else:

if (a < b)

precio = a;

else

precio = b;

8.1. Operador de negacion

Para negar el resultado de cualquier expresion booleana se usa el operador de negacion, elcual se indica con un signo de exclamacion de cierre (!). De esta forma si cualquier expresionevalua a true se hace false al ser precedida por el operador de negacion, y una expresionfalse precedida por este mismo operador se hace true.

Por ejemplo, suponer que el aseguramiento premium de un carro mensual es de $2,000 si laedad del conductor es 25 o menos, y de $1,250 si tiene 26 o mas. Cada una de las siguientessentencias if...else asigna los valores premium correctamente.

if (edad <= 25) if (!(edad <= 25))

premium = 2000; premium = 1250;

else else

premium = 1250; premium = 2000;

if (edad >= 26) if (!(edad >= 26))

premium = 1250; premium = 2000;

else else

premium = 2000; premium = 1250;

Las sentencias con el operador ! son algo difıcil de leer, particularmente porque requieren eldoble conjunto de parentesis. Usar el operador ! es claro cuando el valor de una variable boo-leana es probada. Por ejemplo, una variable inicializada como boolean suficienteMaduro

19

Page 20: Decisionescomputo.fismat.umich.mx/computacion/computacion1/actividades/decision... · 1. Planeaci on de la l ogica de decisi on Los programadores generalmente planean las partes complejas

= (edad>=25); se puede convertir en parte de la expresion relativamente facil de leerif(!suficienteMaduro)...

9. Precedencia de operadores

Se pueden combinar tantos operadores && o || como se necesiten para hacer una decision.Supongase que se quiere premiar con puntos extras (definidos como EXTRA) para cualquierestudiante que reciba una calificacion perfecta en algunos de las cuatro pruebas, se podrıaescribir una sentencia como la siguiente:

if (calificacion1 == PERFECTA || calificacion2 == PERFECTA ||

calificacion3 == PERFECTA || calificacion4 == PERFECTA)

extra = EXTRA;

else

extra = 0;

Se puede combinar cualquier cantidad de operaciones && o || en una expresion, pero se debetener cuidado cuando se combinen. Las operaciones aritmeticas tienen diferentes preceden-cias que hacen una diferencia al ser evaluada la expresion. En una expresion aritmetica, lamultiplicacion y la division son siempre hechas antes que la suma o la resta. El cuadro 1muestra la precedencia de los operadores revisados.

Cuadro 1: Precedencia de los operadores revisados.Precedencia Operador(es) Sımbolo(s)Mas alta Negacion logica !

Intermedia Multiplicacion, division, modulo * / %

Adicion, substraccion + -

Relacionales > < >= <=

Igualdad == !=

Y logico &&

O logico ||

Condicional ?:

Mas baja Asignacion =

En general, el orden de precedencia es similar con el uso algebraico comun. Observar que eloperador && tiene mayor precedencia que el operador ||. Considerar los siguientes codigos,intentados para ser parte del programa de aseguramiento de una empresa, que determinansi un cargo premium adicional debe ser cargado a un conductor que cumpla ambos de lossiguientes criterios:

Tiene mas de dos multas de transito o es menor de 25 anos

20

Page 21: Decisionescomputo.fismat.umich.mx/computacion/computacion1/actividades/decision... · 1. Planeaci on de la l ogica de decisi on Los programadores generalmente planean las partes complejas

Es hombre

// Asigna cargo premium extra incorrectamente

// ya que el operador && es evaluado primero.

if (multasTransito > 2 || edad < 25 && sexo == ’H’)

premiumExtra = 2000;

// Asigna cargo premium extra correctamente

// La expresion dentro de los parentesis anidados se evalua primero

if ((multasTransito > 2 || edad < 25) && sexo == ’H’)

premiumExtra = 2000;

Si consideramos una mujer conductora de 30 anos con tres multas de transito; de acuerdo alos criterios dados, a ella no se le deberıa asignar el premium extra porque ella no es hombre.Para la primera expresion como el operador && toma precedencia, ası edad < 25 && sexo

== ’H’ se evalua primero y el resultado es false ya que la expresion edad < 25 es false

y por lo tanto, al cortocircuitarla seguira siendo false. Como el valor de la variable dela cantidad de multas es mayor que 2, la expresion entera es true, y $2000 es asignado apremiumExtra, lo cual no deberıa ser.

En la segunda sentencia if, se agregaron parentesis para que el operador || sea evaluado pri-mero. La expresion con los parentesis agregados es true porque el valor de multasTransito

es 3. Ası la expresion evoluciona a true && sexo == ’H’. Como el sexo no es ’H’, el valorde la expresion entera es false, y a premiumExtra no se le asigna $2,000.

Una forma de recordar la precedencia de los operadores Y y O, es que estos son evaluadosen orden alfabetico inverso.

Las siguientes dos convenciones es importante que se tengan en cuenta:

El orden en el cual se usen los operadores hace la diferencia.

Siempre se puede usar parentesis para cambiar la precedencia o hacer las intencionesmas claras.

10. Decisiones en constructores

Se pueden emplear decisiones dentro de los constructores o los metodos mutadores, paracontrolar la asignacion de valores permitidos en campos de objetos.

Por ejemplo, suponer que se ha creado una clase Empleado como el que se muestra en elcodigo 5. La clase contiene dos campos que guardan el numero identificador del empleadoy el pago. El constructor acepta valores para estos campos como parametros, pero en vez

21

Page 22: Decisionescomputo.fismat.umich.mx/computacion/computacion1/actividades/decision... · 1. Planeaci on de la l ogica de decisi on Los programadores generalmente planean las partes complejas

de simplemente asignar los parametros a los campos, el codigo determina si cada valoresta dentro de los lımites permitidos para el campo. Una logica similar podrıa ser usada encualquier metodo de asignacion para la clase. Al usar decisiones se asegura que los campostengan valores validos.

1 public class Empleado {2 private int numEmp;3 private double ta r i f aPago ;4 public f ina l int NUM MAX EMP = 19999;5 public f ina l double PAGO MAX = 1 2 0 . 0 0 ;6 Empleado ( int num, double pago ) {7 i f (num <= NUM MAX EMP)8 numEmp = num;9 else

10 numEmp = NUM MAX EMP;11 i f ( pago <= PAGO MAX)12 ta r i f aPago = pago13 else14 ta r i f aPago = 0 ;15 }16 public int getNumEmp( ) {17 return numEmp;18 }19 public int getTar i faPago ( ) {20 return ta r i f aPago ;21 }22 }

Codigo 5: La clase Empleado con un constructor que realiza decisiones.

22