Está en la página 1de 9

TECNOLOGÍA DE

COMPUTADORES PRÁCTICA 1

Ainara del Barco Ventura – 100315414


100315414@alumnos.uc3m.es
Juan Manuel Grande González – 10031527
100315277@alumnos.uc3m.es
ÍNDÍCE
1. EJERCICIO 1 pág 2

2. EJERCICIO 2 pág 3

3. EJERCICIO 3 pág 4-5

4. EJERCICIO 4 pág 5

5. EJERCICIO 5 pág 6

6. EJERCICIO 6 pág 6

7. BATERÍA DE PRUEBAS pág 7-8

8. CONCLUSIONES Y PROBLEMAS pág 8

1
EJERCICIO 1

Apartado a
Inicializamos un entero con el nombre 'n' que representará el número de iteraciones necesarias
para que Sn=Sn+1.
Inicializamos dos variables de tipo float las cuales representaran a cada serie y creamos un
bucle que mientras la variable 'a' (que representa Sn) sea distinta de la variable 'b' (que
representa Sn+1) se incrementa su valor en 1/(2^n) donde el exponente se calcula a través de
una función implementada llamada 'elevar'.

Apartado b
Creamos dos variables para cada serie. La primera tiene dos variables tipo INT, 'a' que será la
variable de la serie y 'm' que será el contador para saber a la potencia que eleva.
Al igual que antes comprobamos en un bucle que si sumamos 1 al número total que hay en la
variable a (nuestra serie) no se desborda, si esto es así llamamos a la función elevar pasándole
por parámetro el valor de n que es la potencia a elevar que tenemos que elevar 2.
Antes de que la serie se desborde (porque a+1<0) se saldrá del bucle e imprimirá el valor total
de a.
La segunda serie tiene una variable tipo int 'n' que tendrá la función de contador para elevar la
variable 'b' de tipo long y será con la que operemos en el bucle que hemos creado para la serie
a. También comprobando que b+1 sigue siendo mayor de 0 (y no se ha desbordado)
Antes de que la serie se desborde (porque b+1<0) se saldrá del bucle e imprimirá el valor total
de b.

PREGUNTAS:
 ¿Cuál es el valor máximo de iteraciones con precisión simple?24 es el valor de la
variable contador que se incrementa mientras que la serie es distinta a la serie +1.
 ¿Cuál es el valor máximo de iteraciones con precisión doble?53, como el tipo de dato
doble es mayor que un simple el número de iteraciones será también mayor.
 ¿Cuál es el tamaño en bits del tipo int? 32 bits. Cuando creamos el bucle tenemos la
variable ‘n’ como contador que indica a que potencia estamos elevando el 2 calcular
el valor máximo. Cuando esa variable int desborda el valor que tiene el contador en
ese momento es 32
 ¿Cuál es el tamaño en bits del tipo long?64 bits, al igual que antes hemos creado otra
variable contador para saber la potencia correspondiente a elevar el 2. Cuando una
variable long se desborda el valor que tiene ese contador es 64
 ¿Qué ocurre con la precisión si en lugar de utilizar una arquitectura de 32 bits
pasamos a una de 64 bits, o viceversa?
La arquitectura de un ordenador no debería afectar a la precisión, ya que solo influye
en la cantidad de memoria que se usará. En el caso de 32 bits como máximo 4 Gb y en
el de 64 bits es ilimitado.

2
EJERCICIO 2

En este ejercicio se debía completar las funciones intToBinary, intToComp1 e intToComp2


proporcionadas en el código fuente, para que dado un número entero, mostrase el valor en
binario, complemento a 1 y complemento a 2 con 8 bits de precisión.
La función intToBinary transforma un número entero a binario natural con 8 bits de precisión.
En esta función, se transforma el número entero mediante el algoritmo de las sucesiones
sucesivas y se van depositando los resultados en el array de forma inversa, es decir, se recorre
el array del revés, para que así el resultado binario esté correctamente colocado. (El algoritmo
de divisiones sucesivas implementaría los resultados de forma inversa, estando el bit más
significativo en la última posición del array). Para los casos en los que el número es negativo,
se calcula su valor absoluto y se representa sin importar el signo.
La función intToComp1 transforma un número entero a complemento a 1 con 8 bits de
precisión. Esta función se aplica únicamente si el número ingresado es menor estricto que
cero, si no, imprimirá el número en binario natural. Puesto que para calcularlo es necesario
previamente el número en binario natural, nos dimos cuenta que este quedaba guardado en el
array al haberse ejecutado primero la función intToBinary(). Debido a esto no era necesario
volver a convertir el número y no se repetía tanto código. Simplemente se recorre el array y se
intercambian unos por ceros.
La función intToComp2 transforma el número binario a complemento a 2 con 8 bits de
precisión. Al igual que el anterior, solo lo hará si el número es negativo. El algoritmo que se ha
seguido para pasar a complemento a dos, teniendo en cuenta que el número almacenado en el
array era el de complemento a 1, ha sido el de sumar 1 al complemento a 1. Para esto se ha
“simulado” la suma recorriendo el array desde la última hasta la primera posición siempre y
cuando el dato almacenado fuese un 1. Cuando esto sucede, se pone un cero como resultado
de sumar 1+1 y se pasa a la siguiente posición. El bucle sigue funcionando hasta que se
encuentre un 0, (en cuyo caso se pone un 1 como resultado de la llevada) o se acabe el array.
Algo a destacar en este ejercicio es que la librería BitLibrary proporcionada, no deja introducir
números fuera del rango -128, 127, cuando el rango de binario natural con 8 bits de precisión
es hasta 255 (2^(8)-1). Esto sucede porque en el caso del complemento a 1 y el complemento a
2, el rango cambia a 2^7. En cuanto al cero, se ha tomado la decisión de que pertenezca al
grupo de los positivos, es decir, no tiene Ca1 ni Ca2.

PREGUNTAS
a) Calcular el número de números representables entre 5 y 6 y entre 21 y 22.
Para realizar esto, se ha usado el ejercicio 5, y un bucle que itera el método
NextDown() desde 6 hasta 5 y desde 22 a 21. Los resultados obtenidos son:
Entre 5 y 6: 2097152 números = 2^19.
Entre 21 y 22: 524288 números = 2^21.
Hay más números representables entre 21 y 22 porque el exponente es mayor.

3
EJERCICIO 3

El objetivo de este ejercicio era transformar un número decimal recibido por parámetro al
formato IEEE754.
En primer lugar, se define un método recursivo elevar() que realiza la función de pow() ya que
esta última no está permitida usarla en el ejercicio. Nótese que el método elevar definido no
contiene el caso de un exponente negativo ya que no iba a ser necesario en la realización del
ejercicio. También se define el método modulof2() que realiza el módulo de un float entre 2,
ya que el operador % no es válido para este tipo de datos.

Antes de aplicar el algoritmo propio para pasar a coma flotante, se estudian los casos
especiales:
-NaN: Sin hacer uso del API de C, una de las formas en las que reconoce un NaN, es
comparando el valor que introducen por parámetro consigo mismo. Si esto no sucede
entonces se ponen por defecto todos los bits a 1.
-Cero: Para hacer el -0 se ha multiplicado -1 por cero y 1 por cero para el caso positivo. Pone
todo como cero y según el signo el bit es igual a 1 o a 0
-Infinito: Para simular el infinito se ha seguido la estrategia de dividir entre 0.0. Se pone 1’s en
el exponente, 0’s en la mantisa y 1 o 0 en el bit de signo dependiendo si es menos infinito o
más infinito.

Una vez solucionados los casos especiales, hemos dividido la conversión a IEEE754 en 3 partes:

1. Bit de signo: si el número es positivo se pone un 0 en la primera posición del array y si es


negativo un 1.

2. Mantisa: Aunque esta es la parte de la mantisa principalmente, también se calcula el


número de posiciones que hay que correr la coma aprovechando que hay que normalizarla,
para que luego sea más fácil la obtención del exponente.
La estrategia que se ha seguido para realizar esto, ha sido separar el número que se recibe por
parámetro en parte entera y decimal. Se usan floats para guardar ambos resultados.
Definimos un auxiliar que recorrerá la mantisa (auxM) y se posiciona en la posición 8 del array
ya que, aunque esta posición pertenece al exponente, podemos sobrescribirlo después al
introducir el exponente y que, de momento, el bit que se coloque en esta posición sea el bit
implícito. Si el número entero es cero, se pasa directamente a convertir la parte decimal, si no,
calculamos el número de bits que necesitaremos y nos creamos un array auxiliar que será
donde depositemos el numero convertido a binario. Una vez hecho esto, copiamos los bits al
array pasado por parámetro numberIEEE754[ ].
Definimos la variable exponente que será igual al tamaño de nuestro array menos 1 y
usaremos para calcular E.
A continuación pasaremos la parte decimal mediante el algoritmo de multiplicar por 2. Para el
caso de que exista un número entero distinto de cero, simplemente continuamos poniendo
bits a continuación del ultimo bit que representaba el número entero, si no, el algoritmo es el
mismo, con una excepción. Puesto que no conocemos cuantos ceros hay antes de que

4
aparezca el primer 1 para poder normalizarlo, mientras que en la posición 8 del array (la que
usábamos como bit implícito) haya un cero, movemos todas las posiciones hacia la izquierda y
continuamos rellenando el final con el algoritmo hasta que se normalice la mantisa.
Definimos que la variable exponente será igual al número de veces que hayamos tenido que
desplazar el array hacia la izquierda.

3. Exponente: Calculamos el exponente sumándole 127 y lo convertimos a binario depositando


los bits recorriendo el array desde la posición 8 hasta la 1 para que quede correctamente
ordenado y rellenando con ceros las posiciones sobrantes (dado que el array inicial está lleno
con 0’s y 1’s aleatorios).

EJERCICIO 4

En este ejercicio nos llegaba un número binario por parámetro en formato IEEE754 y el
objetivo era convertirlo a decimal.
La estrategia que se ha seguido para la resolución de este ejercicio es la siguiente:
1) Separar el exponente y pasarlo a decimal:
Recorremos el array pasado por parámetro desde la posición 1 hasta la 8 (ambas incluidas)
pasando cada número a binario de manera que obtenemos el exponente con exceso 127. Para
obtener el exponente real le restamos 127 y lo guardamos en 'E'.
2) Preguntar si es mayor o menor que cero para saber si tiene parte entera o solo decimal y
convertirlo
Comprobamos si el exponente real ‘E’ es mayor que cero para saber si tiene parte entera, de lo
contrario solo tendría parte decimal.
Si tiene parte entera la pasamos a decimal recorriendo los bits de la mantisa con el algoritmo
de paso de binario a decimal y no paramos hasta que finaliza la mantisa, por lo que también
convertirá a decimal los decimales de la mantisa. Una vez hecho esto comprobaremos el bit de
signo y retornaremos el valor finalizando el método.
Si no tiene parte entera, o su parte entera es 1, usamos un array auxiliar llamado auxD, donde
vamos guardando los bits de la mantisa. Copiamos ceros en este array hasta que el exponente
E es cero y a continuación de esto copiamos los bits alojados en la mantisa.
Por ejemplo, si nuestro exponente E es igual a -32, creamos un array de 32 posiciones (que
serán ocupadas por ceros hasta que llegue el bit implícito cuando E sea igual a cero) mas 23
posiciones de la mantisa (se copiaran los bits de la mantisa). Esto permite que funcione para
números muy pequeños.
Este array se recorre y se transforma su número a decimal.
3) Creamos una variable tipo float donde sumará la parte entera (variable final) y decimal, se
mirará la posición cero (num[0]) y se cambiará el signo si fuese necesario.

Para los casos especiales, se comprueban con una variable denominada bool que cuando es 1
significa false y cuando es 0 true. De esta forma, se recorre el array comprobando, que si son
todo ceros devuelva cero y si son todo unos devuelva NaN (ambas sin tener en cuenta el bit de
signo).

5
EJERCICIO 5

El objetivo de este ejercicio era obtener el número anterior representable en IEEE754


recibiendo por parámetro un número en este formato. Nótese que se ha implementado un
método llamado NumeroDeNums() que permite, mediante un bucle aplicando la función de
este ejercicio, responder a la pregunta del ejercicio 3. Si se quiere ver la funcionalidad de esto,
se puede descomentar el código del main.
Se ha copiado el código del ejercicio 4 en la función IEEE754ToFloat(), ya que la funcionalidad
va a ser la misma.
En el método NextDown(), a parte del código que venía por defecto, se han añadido algoritmos
para obtener el número representable justo anterior. La estrategia que se ha seguido ha sido la
siguiente.
Dentro de este método, llamamos al de IEEE754ToFloat() y guardamos su retorno en una
variable.
Si este número es positivo, simularemos una resta en binario. Para hacer esto, se recorre el
array de derecha a izquierda y va sustituyendo 1 por 0 hasta que encuentre el primer 1, donde
colocará el cero de la llevada.
Si el número es menor o igual a cero, simulamos la suma. Para el caso en el que es cero,
hacemos la suma binaria y cambiamos el signo. Mientras que para los demás solo hacemos la
resta binaria. Esto ocurre, porque en el cero, si hacemos la suma binaria sin cambiar el signo el
número sería positivo, y si hacemos la resta binaria como la tenemos definida, obtenemos un
NaN. Para hacer la suma binaria se ha seguido un algoritmo en el que se recorre el array de
derecha a izquierda y va sustituyendo 0 por 1 hasta que encuentra el primer 0, donde pone el
1 de la llevada.
Para el caso del NaN, no hacemos nada, devolvemos NaN de nuevo.

EJERCICIO 6

El objetivo era convertir un número decimal a formato IEEE754 en doble precisión. Para hacer
esto, se ha usado prácticamente la misma estrategia que en el ejercicio 3, con la salvedad de
que los arrays se recorren para 64 bits en lugar para 32 bits y el exponente, al tener 11 bits,
para calcular su valor, se hace con E+1023.

Cabe destacar, que dado que se realizan operaciones aritméticas con float, este va perdiendo
precisión de forma que, por ejemplo, en el caso de 0.3 que es un número periódico, acaba
valiendo 0.5 por lo que no extiende la periodicidad en la mantisa a 64 bits.

6
BATERÍA DE PRUEBAS

Ejercicio 1:
Al tratarse de un ejercicio en el que no se introduce nada por parámetro las pruebas realizadas
son la correcta obtención de respuestas en cuanto a los distintos apartados.

Ejercicio 2:
Para comprobar el correcto funcionamiento del programa se han utilizado las siguientes
pruebas:
 Introducir un número positivo entre 0 y 127, por ejemplo el 54. Todos los resultados
en binario deben ser 00110110
 Introducir el 127 (extremo). El resultado obtenido es 01111111 en todos los campos.
 Introducir número mayor que 127. No nos lo permite porque se sale del rango.
 Introducir un número negativo entre 0 y -128, por ejemplo -7. El binario debe ser igual
al valor absoluto de -7 (00000111) el Ca1 resultado de intercambiar 0’s por 1’s
(11111000) y el Ca2 la suma binaria de 1 al Ca1 (11111001).
 Introducir -128 (extremo). El resultado obtenido es 10000000 en la parte binaria,
01111111 en el Ca1 y 10000000 en el Ca2.
 Introducir un número menor que -128. No nos lo permite porque se sale del rango.
 Introducir cero. Imprime cero en todos los campos.

Ejercicio 3:
Para comprobar el correcto funcionamiento se ha comprobado con los siguientes casos:

 Introducir casos especiales, como +inf, -inf, NaN y 0.


o inf --- 0 11111111 00000000000000000000000
o –inf --- 1 11111111 00000000000000000000000
o NaN --- 1 11111111 11111111111111111111111
o 0 --- 0 00000000 0000000000000000000000
 Números normalizados.
o 63.3 --- 0 10000100 11111010011001100110011
o -47.5 --- 1 10000100 01111100000000000000000
 Números no Normalizados. Tanto números muy grandes (8.5e37), como muy
pequeños (8e-21).
o 8.5e37 --- 0 11111100 11111111100100110011110
o 8e-21 --- 0 00111100 00101110001110110100000
 Números fuera del rango de los no Normalizados, para lo que se obtenía infinito si era
positivo o menos infinito si era negativo.

Ejercicio 4:
Las pruebas que se han realizado en este ejercicio son las mismas que en el ejercicio 3 pero
para el caso contrario, es decir, introducir el formato en binario y que retorne el número en
decimal.

7
Ejercicio 5:
Las pruebas realizadas en este ejercicio han sido:

 Casos Especiales. Para el infinito devuelve el último número no normalizado, para el


menos infinito devuelve el menos infinito y para el NaN devuelve el NaN.
 Cero. Devuelve el número negativo justo por debajo de cero.
 Casos Normalizados. Devuelve el número anterior. (Se ha probado con los
normalizados del ejercicio 3).
 Casos no normalizados. Si se pone el número más pequeño no normalizado devuelve
cero. Si se pone el número más grande, si es positivo devuelve el anterior y si es
negativo, menos infinito.

Ejercicio 6:
Las pruebas realizadas han sido las mismas que para el ejercicio 3. Comprobando que se
extendían los bits del exponente.

CONCLUSIONES Y PROBLEMAS

En esta práctica, uno de los mayores problemas radicaba en la imposibilidad del uso de las
librerías de C (sobre todo la librería math) aunque finalmente se permitió el uso de algunos
métodos como Floor y pow.

El mayor problema lo hemos tenido en el ejercicio 3, en los números no normalizados. Al


comienzo, dado que no se podía usar la función floor, para guardar la parte entera del número
usábamos un casting, con el consiguiente resultado de que al guardar un número no
normalizado muy grande se desbordaba y no convertía el número real.

Otro de los grandes problemas has sido reconocer los casos particulares como NaN, 0 e
infinito. Puesto que no se conseguía que reconociese el cero con signo, al final se decidió
poner todo ceros por defecto.

Resumiendo, las principales dificultades eran por no poder usar la librería y porque el curso
anterior estábamos acostumbrados a trabajar con otro lenguaje, por lo que teníamos muchos
fallos de sintaxis en C.

También podría gustarte