[JAVA] Ejercicio: Números

En realidad el nombre de este ejercicio es Ejercicio While, pero yo lo llamo Números.

Este ejercicio fue el que hicimos en la clase pasada del jueves 15, que decia lo siguiente:


Construir una clase que tiene por atributos dos enteros ingresados por el usuario y los siguientes métodos:
  1. multiplicación(): devuelve la multiplicación de los dos números pero mediante sumas sucesivas.
  2. división(): devuelve la división de los dos números pero mediante sumas sucesivas.
  3. primo(): devuelve true si los números (ambos son primos), sino false
  4. amigos(): devuelve true si el primer numero es amigo del segundo.Dos numeros son amigos si la suma de los divisores del primero sin incluir el numero me dan como resultado el segundo y si la suma de los divisores del segundo sin el numero, me dan como resultado el primero.
  5. potencia(): devuelve el primer numero elevado al segundo, pero construido como multiplicaciones sucesivas.

Construir una aplicación que permita crear un objeto y mediante un menú mostrar los métodos. Solo se debe salir cuando el usuario quiera.


Clase plano

class Numeros{

private int numero1, numero2;

/* En este metodo teniamos que hacer que 2 numeros se multiplicaran
* pero mediante sumas sucesivas. Entiendase sucesivo como algo
* continuo como un ciclo, osea en nuestro caso un 'while'.
* La mas pura base de la multiplicacion se basa en la suma sucesiva.
*
* Ejemplo:
* Tenemos como Numero1=2 y Numero2=3. ¿Esto que significa?: que
* el numero 2 tiene que sumarse a si mismo 3 veces. Osea, tenemos
* que: 2+2+2 = 6. Eso es una suma sucesiva y es lo que tenemos
* que llevar a nuestro lenguaje de programacion.
*
* Ya nos dimos cuenta que lo que necesitmos para aquello es usar
* el ciclo 'while' de tal forma que sume 'Numero1' tantas veces
* como diga 'Numero2'. ¿Como saber cuantas veces he sumado 'Numero1'?
* Usando un CONTADOR, que en este caso tiene el nombre de 'i'.
* Entonces decimos que mientras 'i' sea menor que 'Numero2' haga el
* proceso de guardar en 'resultado' la suma sucesiva de 'Numero1'.
* Por cada suma que haga, se le aumenta el valor en 1 a el contador
* 'i'. Pero aun falta algo. Y es el lugar en donde ira guardando esa
* suma. En este caso ese lugar se llama 'resultado' y por cada vuelta
* que de el 'while' a 'resultado' se le suma 'Numero1'.
*
* Traza:
* | Numreo1 | Numero2 | Resultado | i |
* -------------------------------------
* | 2 | 3 | 0 | 0 | // Valores iniciales
* | 2 | 3 | 2 | 1 |
* | 2 | 3 | 4 | 2 |
* | 2 | 3 | 6 | 3 | // 3 no es menor que 3. Fin 'while'.
* -------------------------------------
*/


int multiplicacion(){

int resultado=0, i=0;

while(i < numero2){ // Mientras 'i' sea menor que 'numero2'

resultado=resultado+numero1; // Sumamos 'numero1' a 'resultado'
i++; // +1 al contador. OJO!: 'i++' es lo mismo que 'i=i+1'

}

return resultado; // Devolvemos 'resultado'

}

/* Puede que este metodo se vea un poco parecido al anterior, pero
* no lo es. El razonamiento de este es bastante distinto al anterior
* y en vez de sumas sucevias tenemos restas sucevias.
*
* Hay que partir preguntandose como saber mediante restas sucevias
* cuanto es A/B. Sabemos que la division nos ayuda a resolver cuantas
* veces cabe B en A. Por ejemplo: 8/2 = 4. Entonces 2 cabe 4 veces en
* 8. ¿Pero como llevamos eso a nuestro lenguaje y mediante restas
* sucevias?. Simple, es cosa de hacer un ciclo que vaya restando A-B
* mientras A sea mayor que B y almacenando en un contador cuantas
* veces se logro hacer esa operacion. Y luego devolver nuestro contador
* ya que es el, el que nos dira cuantas veces cabe B en A.
*
* Es muy importante usar una COPIA de 'Numero1', por
* el simple motivo que en este caso necesitamos trabajar y modificar
* un valor que esta entro del objeto. y no podemos trabajar directamente
* con el valor original para no perderlo. Digamos que tenemos un numero X
* con un valor X, y en un metodo X trabajamos DIRECTAMENTE con el para
* que nos entregue X resultado. Para llegar a ese X resultado
* necesitamos restarle cosas al numero, sumarle cosas, multiplicar ese
* numero, etc. Hacer cosas con ese numero. Luego de hacer todo eso
* obtenemos nuestro resultado. Todo bien, hasta que llamamos a otro
* metodo que tambien necesita trabajar con ese numero X y su valor
* ORIGINAL. Pero no va a trabajar con su valor ORIGINAL, si no con
* un valor modificado por el metodo anterior. Para que no suceda eso
* y todos los metodos puedan trabajar con los valores del metodos sin
* afectarlos se usan COPIAS de los valores en los meteodos.
*
* Otro detalle importante es que cambia nuestra condicion del 'while'.
* Esta vez dice que mientras 'copia' (entiendase como 'numero1') sea mayor
* o igual que 'numero2' vamos a restar a 'copia' lo que se encuentra en
* 'numero2'. Y luego aumentaremos el valor del contador 'i' en +1, que
* vendria a ser la cantidad de divisiones. ¿Por que menor o igual?.
* Porque en el caso de que tengamos dividiendo dos numeros iguales
* devolveria 0 como resultado ya que no entraria al 'while' porque no
* cumpliria la condicion.
*
* Hagamos una traza con los valores 9(copia de numero1) y 2:
* | Copia | Numero2 | i |
* ----------------------
* | 9 | 2 | 0 | // Valores iniciales
* | 7 | 2 | 1 |
* | 5 | 2 | 2 |
* | 3 | 2 | 3 |
* | 1 | 2 | 4 | // 1 menor que 2. Fin 'while'
* -----------------------
*
* Esta forma de division mediantes restas sucevias NO entrega decimales
* (cosa obvia) por lo tanto siempre va a entregar el valor entero
* de una division.
*/

int division(){

int resultado=0, i=0, copia=numero1;

while(copia > numero2){ // Mientras 'copia' se mayor o igual que 'numero2'

copia=copia-numero2; // Restamos 'numero2' a 'copia'
i++; // +1 al contador

}

return i; // Devolvemos la cantidida de restas sucevias realizadas
}

/* Para saber si un numero es primo o no tiene que cumplir una condicion:
* que solo sea divisible por el mismo y por 1. Osea solo tener 2 divisores.
*
* ¿Como sacar los divisores de un numero?. Primero tenemos que tener claro
* que es un divisor. Un numero es divisor de otro cuando el RESTO de la
* division de ellos es igual a 0. Ahora que sabemos si un numero es
* divisor de otro, debes pensar como sacar TODOS los divisores de un numero.
* Para eso tenemos que recorrer el numero desde 1 hasta si mismo. Osea, si
* queremos sacar el divisor de 10, tenemos que dividirlo desde 1 hasta 10 e
* ir preguntando en todas las divisiones de 1 a 10 cuales dieron resto 0.
* Sabiendo la cantidad de divisones que dieron resto 0, podemos saber si un
* numero es primo o no.
*
* Para poder dividir un numero desde 1 a si mismo tenemos que usar un ciclo
* 'while', tener un divisor y un contador de divisores. Para aquello hay
* que tener encuenta lo siguiente.
*
* 1) En este caso NO se usa una copia del numero, ya que el numero no sera
* tratado, modificado, alterado de ninguna forma. En este caso se usa
* como un valor estable para obtener un resultado.
*
* 2) 'i sera nuestro numero divisor que ira desde 1 hasta el numero necesario.
* OJO: Este debe partir en UNO y no en CERO, ya que la division por cero
* NO EXISTE.
*
* Ahora bien, ¿como saber si un numero es divisor?. Como explique anteriormente
* saber si un numero es divisor de otro se ve con el resto, lo cual en Java
* es el %. Entonces preguntamos:
*
* if(copia_numero%i == 0) { es divisor }
*
* Arriba estamos diciendo que si al dividir 'copia_numero' por 'i' nos da un
* resto igual a cero significa que 'i' es divisor del numero. ¿Entonces?
* Es ahi en donde necesitamos guardar esa informacion en otro contador.
* Cuando se cumpla el caso de arriba se necesita aumentar en uno el contador
* de divisores indicando que fue encontrado otro divisor y agregandolo a la
* cuenta.
*
* Por ultimo lugar, luego del termino del 'if' se aumenta en +1 'i'. De este
* modo 'i' va a ir desde 1 hasta el numero en si mismo. Y va a ir diviendo el
* numero por 1, 2, 3, etc...
*
* Una traza con el numero 6:
* | Numero | i | divisores |
* --------------------------
* | 6 | 1 | 0 | // Valores iniciales
* | 6 | 1 | 1 | // 6/1 -> 1 es divisor -> divisores + 1
* | 6 | 2 | 2 | // 6/2 -> 2 es divisor -> divisores + 1
* | 6 | 3 | 3 | // 6/3 -> 3 es divisor -> divisores + 1
* | 6 | 4 | 3 | // 6/4 -> 4 NO es divisor
* | 6 | 5 | 3 | // 6/5 -> 5 NO es divisor
* | 6 | 6 | 4 | // 6/6 -> 6 es divisor -> divisores + 1
* --------------------------
*
* Esa traza devuelve como resultado que 6 tiene 4 divisores, que son
* 1, 2, 3 y 6.
*
* Una traza con el numero 5:
* | Numero | i | divisores |
* --------------------------
* | 5 | 1 | 0 | // Valores iniciales
* | 5 | 1 | 1 | // 5/1 -> 1 es divisor -> divisores + 1
* | 6 | 2 | 0 | // 5/2 -> 2 NO es divisor
* | 5 | 3 | 0 | // 5/3 -> 3 NO es divisor
* | 5 | 4 | 0 | // 5/4 -> 4 NO es divisor
* | 5 | 5 | 2 | // 5/5 -> 5 es divisor -> divisores + 1
* --------------------------
*
* Esa traza devuelve como resultado que 5 tiene 2 divisores, que son
* 1 y 5. Osea... es PRIMO!
*
* Hay que repetir el proceso con los 2 numeros que tenemos, 'numero1'
* y 'numero2' y luego en un 'if' final preguntar si los DOS numeros
* tienen solo 2 divisores (osea los DOS son primos) devuelve 'true'
* de lo contrario 'false'.
*/

boolean primo(){

int i=1, divisores_num1=0, divisores_num2=0;

while(i <= numero1){ // Mientras 'i' sea menor o igual a 'numero1'

if(numero1%i == 0){ // Si 'numero1'%'i' es igual a 0

divisores_num1++; // Es divisor
}

i++;
}

/* Ojo que aqui lo unico que hago es restablecer el contador 'i'
* a su valor original UNO para no usar otro contador y asi
* re-utilizar el mismo.
*/

i=1; // Restablecemos el contador 'i' = 1 para usarlo en el siguiente while

while(i <= numero2){ // Mientras 'i' sea menor o igual a 'numero2'

if(numero2%i == 0){ // Si 'numero2'%'i' es igual a 0

divisores_num2++; // Es divisor
}

i++;
}

if(divisores_num1 == 2 && divisores_num2 == 2){ // Si los 2 son primos

return true;

} else {

return false;
}
}

/* Dos numeros son amigos tal que la suma de los divisores propios de A den B y
* la suma de los divisores de B den A. Entiendase 'divisores propios' como
* todos los divisores de un numero sin el mismo. Osea, divisores propios de 6:
* 1,2 y 3. Se excluye el numero 6.
*
* Como ya sabemos como sacar los divisores de un numero, sera un poco mas facil
* entender el funcionamiento de esta parte. Pero aun asi hay cosas que explicar,
* como la gran diferencia que ahora no necesitamos CONTAR cuantos divisores
* tiene X numero, si no que hay que SUMARLOS y que la condicion de nuestro 'while'
* cambia, de 'i'<='numero' a 'i'<'numero'. Ya que debemos EXCLUIR el mismo 'numero''.
*
* Si nos fijamos en el codigo, la condicion del 'if' es la misma, pero esta vez
* no usamos un contador, si no que sumamos divisores. Entonces debemos tener un
* lugar donde ir guardando la suma de estos para luego preguntar si la suma
* de los divisores, para luego hacer la comparacion pertinente.
*
* Fijense en esta linea:
*
* if(divisores_num1 == numero2){
*
* Esta linea va solo por un metodo de optimizacion de codigo. Ya que si no se cumple
* eso, seria inutil revisar el segundo numero, ya que aunque se cumpla en el segundo
* caso seguiran siendo NO AMIGOS. Asi se evita hacer un 'while' innecesario y
* devuelve inmediatamente 'false' indicando que NO son amigos. En el caso de que
* esa condicion se cumpla se hace el mismo trabajo que hicimos con el primer numero
* pero esta vez con el segundo. Luego preguntamos si la suma de los divisores del
* segundo numero es IGUAL al primer numero devolvemos 'true' indicando que SI son
* amigos, de lo contrario devolvemos 'false'.
*/

boolean amigos(){

int i=1, divisores_num1=0, divisores_num2=0;

while(i < numero1){

if(numero1%i == 0){

divisores_num1=divisores_num1+i;

}

i++;

}

if(divisores_num1 == numero2){

i=1; /// Restablecemos el contador 'i' = 1 para usarlo en el siguiente while

while(i < numero2){

if(numero2%i == 0){

divisores_num2=divisores_num2+i;

}

i++;

}

if(divisores_num2 == numero1){

return true;

} else {

return false;

}

} else {

return false;

}

}

/* Sabemos que una potencia en palabras simples es mutiplicar un numero (base)
* tantas veces lo indique otro (exponente).
*
* Entonces necesitamos multiplicar el 'numero1' tantas veces indique 'numero2'.
* Debemos recorrer 'numero2' desde 1 hasta si mismo. Para aquello usamos un
* contador 'i' que se vaya aumentando en +1 por cada vuelta que de el 'while'. Y
* de este modo iremos almacenando en 'resultado' las multiplicaciones de 'numero1'
* o mejor dicho las multiplicaciones sucevias de 'numero1'.
*
* Traza con los valores 2 y 4:
* | Numero1 | Numero2 | i | Resultado |
* -------------------------------------
* | 2 | 4 | 0 | 0 | // Valores iniciales
* | 2 | 4 | 1 | 4 | // 2*2 = 4
* | 2 | 4 | 2 | 8 | // 4*2 = 8
* | 2 | 4 | 3 | 16 | // 8*2 = 16 <- Resultado
* -------------------------------------
*/

int potencia(){

int i=0, resultado=1;

while(i < numero2){ // Mientras 'i' sea menor que 'numero2'

resultado=resultado*numero1; // Almacenamos 'resultado'*'numero1'
i++; // Aumentamos el contador

}

return resultado; // Devolvemos 'resultado'

}

}


App

class AppNumeros{

public static void main(String[]arg){

int numero1, numero2, op=1;

while(op!=0){

System.out.println("");
System.out.println("Numero 1: ");
numero1=Leer.datoInt();
System.out.println("Numero 2: ");
numero2=Leer.datoInt();

Numeros uno = new Numeros(numero1, numero2);

while(op!=0 && op!=6){

System.out.println("");
System.out.println("[1] Multiplicacion");
System.out.println("[2] Division");
System.out.println("[3] Primo");
System.out.println("[4] Amigos");
System.out.println("[5] Potencia");
System.out.println("");
System.out.println("[6] Nuevos Numeros");
System.out.println("[0] Salir del Programa");
System.out.println("");
op=Leer.datoInt();

switch(op){

case 1: // Multiplicacion

System.out.println("Numero 1 por numero 2: "+uno.multiplicacion());
break;

case 2: // Division

System.out.println("Numero 1 dividido numero 2: "+uno.division());
break;

case 3: // Primos

if(uno.primo()){

System.out.println("Los 2 numeros son primos!");

} else {

System.out.println("Ambos o uno de ellos no son primos :(");

}
break;

case 4: // Amigos
if(uno.amigos()){

System.out.println("Son amigos :)");

} else {

System.out.println("No son amigos :(");

}
case 5:

System.out.println("Numero 1 elvedao numero 2: "+uno.potencia());
break;

case 6: // Crear nuevos numeros o salir
case 0:
break;

default: System.out.println("No es una opcion valida. Intente nuevamente");

}
}
}

System.out.println("Adios!");

}

}

Etiquetas Etiquetas: , |

0 comentarios: