Referencia y guia: Cay Horstmann, Big Java Edicion 4
Capitulo 4 parte I
Tipos de datos fundamentales
Metas del capitulo
- Entender un poco sobre los numeros Integer y los Floating-point
- Reconocer las limitaciones de los tipos numericos
- Estar alerta sobre los errores del redondeo y del sobre exeso
- Entender el uso correcto de las constantes
- Escribir expresiones aritmeticas en Java
- El como usar el tipo "String" para manipular caracteres string
- Aprender a leer programas que introduscan y produscan un resultado formateado
Este capitulo se basa en el entendimiento del como manipular numeros y caracteres tipo string en Java. Su nucleo es el dar ejemplos y definiciones utiles para que se tengan como referencias cuando se estudie y practique el como programar en Java.
Se buscaran varias referencias, varios ejemplos, definiciones y experiencias que ayudaran a ver el como algunos tipos de dato numericos tienen limitaciones, debido a la forma como son interpretados bajo el lenguaje binario, y el como afectan al programa. Sabiendo esto muestra el como el lenguaje de programacion Java trabaja, lo demas es cuestion propia. Ademas de darles algunos ejemplos, o referencias. Lo otro sera el como usar el tipo de datos String para manipular caracteres String, el como usar los metodos de la clase String para modificarlos. Y por ultimo la entrada de datos, y la modificacion de la salida de estos de forma original.
4.1 Tipos numerales
En Java, todo valor es una referencia a un objeto, o prtenece a uno de los ocho datos primitivos. http://es.wikipedia.org/wiki/Tipo_de_dato_elemental
Seis de los datos primitivos son para los Integers y dos para los floating-points.
Cada tipo Integer tiene diferentes rangos. Los rangos estan relacionados en potencias de dos, vease 4.1.2. El integer "int" mas grande se puede representar buscando la variable estatica de la clase Integer Integer. MAX_VALUE. Lo opestos seria los mismo pero MIN.VALUE. y su rango es de un aproximado de 2.14billones a -2.14billones.
Por esta razon es muy importante saber el rango de los datos numericos puesto que el sobrepasar su capasidad puede generar una sobrecarga al valor y dar otro tipo de valor no deseado.
Por ejemplo:
int ñ = 1000000;
System.out.println(ñ * ñ); //imprime -727379968, claramente erroneo.
El producto de ñ * ñ es 10 a la 12, donde claramente sobrepasa el 10 a la 9 que puede soportar tal dato numerico. El resultado es truncado para que quepa en el int, cediendo su valor que esta mal. Lamentablemente no existe alerta en el compiler ni alerta prediseñada en el programa que pueda alertar al usuario cuando exista una sobre carga, pero se puede diseñar y para eso se estudia, para aprender de los errores.
En caso de que se calcule de antemano que el eso del int puede tener una sobre carga o exeso, es recomendable usar otro tipo dependiendo del programa, la memoria y la rapidez que debe ser empleada para su trabajo.
Hay una forma de realizar cualquier tipo de funcion aritmetica sin preocuparse mucho por el espacio y esta es el crear un Objeto de la clase BigInteger y elaborar cualquier operacion. Esta clase en mi parecer seguro es empleada en programas extensos y organicos donde no hay posible fin al proceso de calculacion aritmetica, ademas de otro tipo de funciones relacionadas a los sistemas de computador. vease: http://docs.oracle.com/javase/1.4.2/docs/api/java/math/BigInteger.html#BigInteger(byte[])
Problemas de redondeo son un problema serio con los floating-points. Errores de redondeo pueden ocurrir cuando intentan convertir numeros binarios y decimales o entre Integer y floating-points. Cuando el valor no puede ser convertido exactamente, es redondeado hasta el resultado mas cercano. Ejemplo.
double f = 4.35;
System.out.println(100 * f) // da 434.999999999999994
Este problema deriba directo del como el ALU en el procesador esta diseñado. El como es representado el numero en el sistema binario, ya que en este no existe una exacta representacion para la fraccion 1/10, al igual que 1/3.
Por esta misma razon el usar double o cualquier otro dato numerico para calcular formulas finacieras traeria errores y diferencias enormes a la larga. Una de las posible soluciones es el usar la clase BigInteger y crear objetos que cumplan con su funcion adecuada.
Los datos numericos pueden tomar otros datos numericos, pero solo para cambiar de dato.
Se sobre entiende que un int te dara un int y un double un double.
Por ejemplo:
int i = 20;
double d = i; // da 20.0
lo contrario.
double d = 2.33;
int i = d; //daria 2, sacando la parte decimal del valor.
4.1.1 Numero Grandes
Para crear numeros donde no se especifica la cantidad, y no se quiere usar el tipo "double" se crean entonces los objetos llamados Numeros Grandes, de la misma clase BigInteger, o BigDecimal para los decimales.
Estos objetos que son la extencion de la clase Number o Numero, soportan cualquier cantidad de numeros, dependiendo de la memoria que uno tenga. Y como son Objetos, tienen la facilidad de tener metodos, ya que por ser objetos y no tipos primitivos no pueden ser usados los operandos regulares como (+, -, /, *, etc), sino que tienen que ser invocados por medio de metodos especificos.
Vea aqui para mejor informacion:
4.1.2 Numeros Binarios
Hay varias formas del como convertirnumeros decimales y fracciones en numeros binarios.
*Cada decimal tiene su valor por medio de las potencias, esta es la cantidad de valores que tiene cada unidad. 0 al 9. 10 elementos, cada uno representando cuantas unidades tiene.
*Como los numeros binarios tienen como potencia solo dos elementos. El estado "apagado" o "prendido", el 0 y el 1, diseñado para implementarse facilmente al computador por medio de sus circuitos logicos, entre otros.
por eso el metodo para interpretar o convertir los numeros binarios en decimales es parecido a la interpretacion del como esta cumpuesto un numero decimal.
El numero decimal:
435: (4* 10^2) + (3*10^1) + (5*10^0)
El numero binario es similar pero con un paso extra:
1101 = (1*2^3) + (1*2^2) + (0*2^1) + (1*2^0) = 8 + 4 + 1 = 13.
Primero cada posicion tiene su potencia, de la mas alta al 0.
Otro metodo para convertir los numeros binarios en decimales es el siguente:
101011 = por cada binario, comenzando por el primero, se multiplica por dos y luego se le suma 1 si el binario es 1 o 0 si es 0.
101011 = (0 * 2) + 1 = (1 * 2) + 0 = (2 * 2) + 1 = (5 * 2) + 0 = (10 * 2) + 1 = (21 * 2) + 1 = 43
otra forma es la de saber la table hasta el 15 y todas las potencias derivadas de (2*2) (4*2) (8* 2) (16*2)...etc. ya que todos comparten la misma secuencia; 10 = 2; 100 = 4; 1000 = 8; 10000 = 16; 10000 = 32; ...
Lo otro seria convertir las fracciones:
*Las fracciones se pueden observar como la cantidad exacta que tiene un elemento y esto en programacion es increiblemente importante, por lo mismo su precicion es fundamental.
Para convertir un binario a fraccion se implementa el metodo similar usado para los decimales, fraccionandolo por potencias negativas de 2.
111.101 = 7. (1 * 2^-1) + ( 0 * 2^-2 ) + (1*2^-3) = 0.5 + 0 + 0.125 = 7.625
Ejemplo:
1*2^-1 = 1 * 1 / 2 = 0.5
1*2^-2 = 1 * 1 / 4 = 0.25
1*2^-3 = 1 * 1 / 8 = 0.125
Ahora para convertir un decimal en binario se implementa otro metodo.
*Ya que una fraccion es lo que tiene la cantidad exacta del elemento, en este metodo, cuando sobra o queda algo luego de la operacion, esta se interpreta como un 1, sino queda nada, 0
39 / 2 | reminder 1
19 / 2 | reminder 1
9 / 2 | reminder 1
4 / 2 | reminder 0
2 / 2 | reminder 0
1 / 2 | reminder 1
Como se ve, el resto se convierte en 1 y se redondea.
*luego se saca el numero binario de abajo a arriba quedando el 100111
Con las fracciones, ya que no se reduce sino que se expanden, se multiplican por la base binaria, 2.
0.35 * 2 = 0.7
0.7 * 2 = 1.4
0.4 * 2 = 0.8
0.8 * 2 = 1.6
0.6 * 2 = 1.2
0.2 * 2 = 0.4 se repite aqui.
Ver lo que paso aqui significa saber un poco sobre las fracciones y entender que pueden dar exactas o seguir en una especie de ciclo.
Pero es muy importante observar como el 1 es el mismo elemento que sobra en la fraccion y cuando no es 0.
En este metodo se lee representando una fraccion, de arriba a abajo = 0.0101100110...se llena el resto dependiendo del numero de bits que pueda retener el tipo de data primitivo que sea usado.
Hay otro metodo para convertir automaticamente decimales a binarios y binarios a decimales, pero usando la informacio en forma de "string"
Con el metodo Integer.toString(n, 2), dandole el decimal por medio de n, y la potencia como 2(binario)
El otro metodo es el Integer.parseInt(digitString, 2) donde pasas el numero binario en el digistString, y calibras como binario en 2.
Los dos metodos devuelven un String.
Para otro tipo de informacion: http://en.wikipedia.org/wiki/Binary_number
4.2 Constantes
Las constantes son variables estaticas que no cambian de estado una vez iniciadas, ni pueden ser mutadas, son inmutables. Estan diseñadas para no repetir la misma informacion ademas de tenerla como valor fijo.
Ejemplo:
public static final double VALOR_DE_CENTAVO = 0.01;
Las palabras reservadas final transforman la variable en constante. Se escriben en letra mayuscula para diferenciarlas, pero en nada modifican su condicion el hacerlo.
4.3 Operaciones aritmeticas y funciones matematicas
En java existe lo que se llama como Orden de procedencia para los operandos, significa que cuando uno crea un algoritmo, el sistema de computacion, ALU, va a darle prioridad a los operandos que tengan mayor procedencia.
Visita la pagina para ver la tabla:
Por lo mismo ponerle parentesis a las expresiones, el sistema ALU priotiza lo de adentro para luego ejecutar el resto.
Ejemplo:
(a + b) / 2 realiza la operacion entre a y b y luego el resultado lo divide entre 2
distinto a
a + b / 2 donde la division tiene orden de procedencia mas alto que la suma y divide b entre 2 para luego sumarle el resutado a a.
4.3.2 Incremento y decremento
En java hay un operador demaciado util, este que incrementa y decrementa los valores tipo primitivo, en especial los int
class PrePostDemo {
public static void main(String[] args){
int i = 3;
i++;
// prints 4
System.out.println(i);
++i;
// prints 5
System.out.println(i);
// prints 6
System.out.println(++i);
// prints 6
System.out.println(i++);
// prints 7
System.out.println(i);
}
}
Sacado de la pagina: http://docs.oracle.com/javase/tutorial/java/nutsandbolts/op1.html
Aqui se puede ver como el i++ incrementa luego de pasada la instruccion y el ++i antes de pasarla. Lo mismo va con el i-- y el --i
Esta especie de operando se usa mucho en los loops como counter, etc.
4.3.3 Division del Integer
Cada tipo primitivo iria mejor con su tipo, pero aveces esa no es la respuesta y uno tiene que resolver.
El resultado de un double con un int, dependiento en que tipo de referencia guardes el resultado, dara el tipo de referencia.
int e = 4;
double r = 3.3;
r = r + e; // da 7.3
e = r - e; // da 4
4.3.4 Potencias y raices cuadradas
Para realizar las potencias o racices primero se importa la clase Math en el programa, se crea un objeto de esta clase y luego se guarda en cualquier tipo de variable.
vease la informacion de la clase Math: http://docs.oracle.com/javase/7/docs/api/java/lang/Math.html
4.3.5 Redondeando y moldeando
Moldear un elemento significa convertir el elemento para que este pueda ser usado a otro tipo de elemento o variable.
Cuando dos nodos similares tienen que ser comparados, se moldea y convierte el nodo al tipo del nodo que se va a comparar, asi la informacion podra ser interpretada y comparada bajo un solo tipo de elemento.
por aqui se puede ver, un poco avanzado, la funcion del cast:
Sirve para convertir un objeto abstracto en el tipo de objeto especifico.
Capitulo 4 continuara en la parte II
No comments:
Post a Comment