LA SUBRUTINA QUE DEVUELVE VALORES se llama función. Una función determinada, solo puede devolver valores de un tipo concreto, denominado tipo de retorno (return type) de la función. La llamada a una función, normalmente aparece en los lugares en que el ordenador esta esperando encontrarse un valor, como en la parte derecha de una instrucción de asignación, como parámetro en una llamada a subrutina, o en el medio de alguna expresión. Las funciones de valor boleano también pueden ser usadas como condiciones en las instrucciones if, while o do.
También es correcto el emplear una llamada a función en una instrucción como si fuera una subrutina normal. En esta caso, el ordenador ignorará el valor calculado por la subrutina.
Esto a veces tiene sentido. Por ejemplo, la función console.getln(), que devuelve un tipo String, lee y devuelve la línea tecleada por el usuario.
Normalmente esa línea devuelta, es asignada a una variable en una instrucción
«String name=console.getln();«
para que el programa la emplee mas tarde. Sin embargo, esta función también es útil emplearla como subrutina con la llamada
«console.getln();«
para que lea y descargue todo lo que se haya tecleado hasta el siguiente retorno de carro.
Ya hemos visto y usado funciones como Math.sqrt() y console.getInt(). Lo que no hemos visto, es como escribirlas nosotros.
La función, en principio tiene la misma forma que una subrutina, excepto que tiene que especificar el valor que se va a devolver. Esto se puede realizar con la instrucción return, que tiene esta forma:
return expresión;
Esta instrucción solo pueden aparecer en el interior de la definición de la función, y el tipo de la expresión debe ser el mismo que el que se ha especificado como tipo de retorno para esta función. Cuando el ordenador ejecuta la instrucción return, evalúa la expresión. finaliza la ejecución de la función y usa el valor de la expresión como valor de retorno de la función.
Dentro de un método ordinario, que ha declarado como tipo de retorno «void» puede utilizar la instrucción return para finalizar la ejecución del método inmediatamente y devolver el control al punto del programa que lo invocó, pero esta instrucción return no puede emplear la expresión.
Es una forma bastante usual de finalizar la ejecución de una subrutina, pero no es obligatorio. Por otra parte, en la función si que es obligatorio la instrucción return con la expresión.
Aquí tenemos una función que podemos emplear en el programa que calcula la secuencia 3N+1. Dado un termino de la secuencia, esta función calcula el siguiente:
static int nextN(int currentN) { if (currentN % 2 == 1) // prueba si N es impar return 3*currentN + 1; // si lo es, devuelve esto else return currentN / 2; // si no, devuelve esto }
Muchos programadores, entre los que me encuentro, prefieren utilizar una instrucción return única, como final real de la función. Esto permite encontrar la instrucción return mas fácilmente. Podemos escoger el escribir la función de esa forma, en el siguiente ejemplo:
static int nextN(int currentN) { int answer; // answer sera el valor de retorno if (currentN % 2 == 1) // prueba si N es impar answer = 3*currentN+1; // si lo es, prepara esto else answer = currentN / 2; // si no, prepara esto return answer; // (Devuelve el valor !No lo olvide!) }
Aquí esta la subrutina que emplea nuestra función nextN.En este caso, la mejora frente a la versión original, no es muy grande, pero si nextN() fuera una función larga que realizara cálculos complejos, entonces si que habría tenido sentido el ocultar la complejidad dentro de la función:
static void Print3NSequence(int startingValue) { // imprimir la secuencia 3N+1 en la consola usando // startingValue como valor inicial de N int N = startingValue; // N es el termino de la secuencia int count = 1; // cuenta el numero de términos console.putln("La secuencia 3N+1 empieza en " + N); console.putln(); console.putln(N); // imprimir el primer termino while (N > 1) { N = nextN(N); // calcula siguiente termino count++; // lo cuenta console.putln(N); // lo imprime } console.putln(); console.putln("Aquí hay " + count + " términos en la secuencia."); } // end of Print3NSequence()
Aquí tenemos algunos ejemplos mas sobre funciones. El primero calcula la letra que se ha de colocar según una escala de valores numéricos:
static char letterGrade(int numGrade) { // devuelve la letra correspondiente // a una escala numérica if (numGrade >= 90) return 'A'; // 90 o superior devuelve A else if (numGrade >= 80) return 'B'; // 80 a 89 devuelve B else if (numGrade >= 65) return 'C'; // 65 a 79 devuelve C else if (numGrade >= 50) return 'D'; // 50 a 64 devuelve D else return 'F'; // cualquier otra cosa devuelve F } // end of function letterGrade()
El tipo del valor de retorno de letterGrade() es char. Las funciones pueden devolver cualquier tipo de valor. Aquí tenemos una que devuelve un valor de tipo boolean:
static boolean isPrime(int N) { // devuelve true si N es numero primo, esto es, // si N es positivo y no es divisible por ningún // numero positivo excepto por 1 y él mismo int maxToTry = (int)Math.sqrt(N); // probaremos de dividir N por números entre // 2 y maxToTry; si N no es divisible por // ninguno de esos números, entonces N es primo. // (observe que Math.sqrt(N) devuelve un valor // de tipo double, el valor debe cambiarse a // tipo int antes de poder asignar // a maxToTry.) for (int divisor = 2; divisor <= maxToTry; divisor++) { if ( N % divisor == 0 ) // prueba si N es divisible return false; // si lo es, no es primo } // al llegar a este punto, N debe ser primo. De otra forma // la función ya habría terminado al ejecutar // la instrucción return en el bucle for. return true; // si, N es primo } // end of function isPrime()
Finalizaré esta sección con la versión completa de programa 3N+1. Esto nos permitirá el emplear la función nextN() en un programa completo.
También tendremos la posibilidad de mejorar el programa definiendo la impresión de los términos de la secuencia en columna, con varios términos en cada línea.
Así haremos la salida mas presentable. La idea es fácil. Tenemos que controlar cuantos términos se ha escrito en la línea actual, cuando el valor alcance un determinado numero, iniciaremos nueva línea.
Para conseguir que los términos aparezcan alineados en columna, usaremos la versión de console.put() con firma put(int,int). El segundo parámetro int indica la anchura de la columna.
Para enseñar otra nueva idea, mi programa especifica el numero de columnas de salida y la anchura de cada columna como constante.
Una constante es como una variable excepto que su valor no puede cambiar nunca mientras el programa este funcionando. (para cambiar el valor, deberá editar el programa y recompilarlo).
Las constantes se emplean en los programas porque es mas fácil recordar y entender un nombre que una constante literal.
En Java, una constante se define utilizando en la declaración de la variable el modificador «final«.
La palabra final, indica que la constante esta en su forma final– que el valor asignado es el final y no puede ser cambiado. Mas adelante, veremos que el modificador final también puede ser usado en la definición de métodos.
public class ThreeN { /* Este programa calcula y presenta la secuencia 3N+1 Empieza la secuencia en donde el usuario indique Los términos de la secuencia se imprimen en columnas con varios términos en cada línea. Después de finalizar la secuencia, se informa del numero de términos */ final static int numberOfColumns = 5; // constant indica el // numero de términos en columna final static int columnWidth = 8; // constant indica anchura // en numero de caracteres en // cada columna Console console; // ventana para entrada/salida public static void main(String[] args) { console = new Console(); console.putln("Este programa imprime la secuencia 3N+1 "); console.putln("empezando en el valor que especifique."); console.putln(); int K = 0; do { console.putln("Indique valor inicial;"); console.put("para finalizar programa entre 0: "); K = console.getInt(); // lee valor inicial del usuario if (K > 0) // imprime la secuencia si K is > 0 Print3NSequence(K); } while (K > 0); // continua solo si K > 0 console.close(); } // end main() static void Print3NSequence(int startingValue) { // imprime la secuencia 3N+1 en la consola usando // startingValue como valor inicial de N int N = startingValue; // N representa el termino. int count = 1; // cuenta el numero de términos. int onLine = 1; // onLine cuenta términos en la línea actual. console.putln("La secuencia 3N+1 empieza en " + N); console.putln(); console.put(N, columnWidth); // imprime el primer termino while (N > 1) { N = nextN(N); // calcula siguiente count++; // cuenta el termino if (onLine == numberOfColumns) { // si la línea esta llena console.putln(); //imprime retorno de carro onLine = 0; // y borra contador de términos en línea } console.put(N, columnWidth); // imprime el termino onLine++; // incrementa contador de términos en línea } console.putln(); // final de la línea actual console.putln(); // añade línea en blanco console.putln("Aquí hay " + count + " términos en la secuencia."); } // end of Print3NSequence() static int nextN(int currentN) { // calcula el siguiente termino de la secuencia 3N+1 if (currentN % 2 == 1) return 3 * currentN + 1; else return currentN / 2; } // end of nextN() } // end of class ThreeN
4 comentarios