Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: amgarciac en 24 Julio 2013, 15:45 pm



Título: A un dato de salida se le resta uno sin programarlo así
Publicado por: amgarciac en 24 Julio 2013, 15:45 pm
Buenas tardes, estoy escribiendo un programa que como dato de salida debería de dar 46 -en vez de 45, que es lo que sale sin saber por qué- siendo los de entrada 1.54 y 2. Este es su código:

Código:
#include <iostream> 
using namespace std;

int main()
{
double precio, pagado;
int centimos;
cout << "Escriba precio y dinero entregado: ";
cin >> precio >> pagado;
centimos = 100 * (pagado - precio);
cout << "Hay que devolver " << centimos << " centimos" << endl;
}

¿A qué puede deberse, a un error del flujo de datos (ya me ha pasado otras veces con un while, etc.?


Título: Re: A un dato de salida se le resta uno sin programarlo así
Publicado por: amchacon en 24 Julio 2013, 15:48 pm
A mí me da 46 céntimos  :huh:

(http://imageshack.us/a/img198/7757/8av.png)


Título: Re: A un dato de salida se le resta uno sin programarlo así
Publicado por: amgarciac en 24 Julio 2013, 15:52 pm
En primer lugar gracias por responderme, pero lo preguntaba (siendo no haberlo aclarado en el enunciado) porque se plantea este problema en un libro de programación que estoy leyendo.

Así que entonces, ¿a qué se debe ese error que muestra el problema, de que le salen 45 y no 46? ¿No es nada de ejecución verdad?

Yo pienso que debido a un despiste, haya añadido por ejemplo "centimos-1" (o centimos--), porque a mí me salen 46. Y dudo no sea que sea una pregunta "trampa" la que plantee el problema.

Un saludo


Título: Re: A un dato de salida se le resta uno sin programarlo así
Publicado por: amchacon en 24 Julio 2013, 15:56 pm
Así que entonces, ¿a qué se debe ese error que muestra el problema, de que le salen 45 y no 46? ¿No es nada de ejecución verdad?
Yo lo que hecho ha sido copiar y pegar el código literalmente. Y me ha salido los 46 céntimos, por lo que funciona bien.

Tampoco veo que haya algun error en el código.

Yo pienso que debido a un despiste, haya añadido por ejemplo "centimos-1" (o centimos--), porque a mí me salen 46. Y dudo no sea que sea una pregunta "trampa" la que plantee el problema.
¿Fallo del libro? La cuestión esque el código es correcto y salen los 46 céntimos.


Título: Re: A un dato de salida se le resta uno sin programarlo así
Publicado por: amgarciac en 24 Julio 2013, 16:02 pm
El libro me expone el código tal y como lo he puesto, y a continuación  me pide que escriba el programa y prueba la ejecución con los datos 1.54 y 2. El autor del problema dice que en su máquina obtiene "45 céntimos", preguntándome entonces que cuál creo que es el problema, y que proponga una solución.

Es que no comprendo que me pregunte cuál creo que es el problema. A lo mejor ha restado 1 sin querer. Y ya te digo, que una vez en un while, alcanzaba n-1 y no n que era lo que puse; por ello nada me extraña.

A lo mejor debe limpiar el flujo de datos y/o sumar uno.

Un saludo


Título: Re: A un dato de salida se le resta uno sin programarlo así
Publicado por: eferion en 24 Julio 2013, 16:21 pm
El problema puede venir dado porque los números decimales pueden sufrir una cierta falta de precisión.

Los números expresados en coma flotante tienen una notación diferente a la usada para almacenar números enteros.

En el caso de los números decimales, es complicado encontrar ( con un número finito y relativamente reducido de bits ) una combinación que resulte en la representación exacta del número.

Dicho con un ejemplo: si calculas la representación binaria ( a pelo ) de 0.46 te da

0.46 * 2 = 0.92 -> 1er bit 0
0.92 * 2 = 1.84 -> 2º bit 1
0.84 * 2 = 1.68 -> 3er bit 1
0.68 * 2 = 1.36 -> 4º bit 1
...

Si para representar el dígito decimal con precisión exacta requieres más bits de los que el sistema es capaz de proporcionarte al final eso te obliga a falsear el número almacenado.

Normalmente, que yo sepa, con 32 bits ( un float en un pc típico ), se obtiene una precisión de 6 cifras.

Posiblemente los tiros vayan por ahí... yo me inclino a pensar que, posiblemente, la máquina que comenta el problema es de 16 bits. No lo he calculado, pero no me extrañaría que con 16 bits la precisión máxima fuese de, por ejemplo, 2 dígitos... con lo que al tener 0.45, la precisión se va en el 0.4 y las centesimas podrían bailar.

Si con 16 no se reproduce el problema entonces puede que su máquina sea de 8 bits... calcular el margen de error es posible pero no tengo ganas para ponerme calculadora en mano :)


Título: Re: A un dato de salida se le resta uno sin programarlo así
Publicado por: amchacon en 24 Julio 2013, 16:35 pm
El problema puede venir dado porque los números decimales pueden sufrir una cierta falta de precisión.

Los números expresados en coma flotante tienen una notación diferente a la usada para almacenar números enteros.

En el caso de los números decimales, es complicado encontrar ( con un número finito y relativamente reducido de bits ) una combinación que resulte en la representación exacta del número.

Dicho con un ejemplo: si calculas la representación binaria ( a pelo ) de 0.46 te da

0.46 * 2 = 0.92 -> 1er bit 0
0.92 * 2 = 1.84 -> 2º bit 1
0.84 * 2 = 1.68 -> 3er bit 1
0.68 * 2 = 1.36 -> 4º bit 1
...

Si para representar el dígito decimal con precisión exacta requieres más bits de los que el sistema es capaz de proporcionarte al final eso te obliga a falsear el número almacenado.

Normalmente, que yo sepa, con 32 bits ( un float en un pc típico ), se obtiene una precisión de 6 cifras.

Posiblemente los tiros vayan por ahí... yo me inclino a pensar que, posiblemente, la máquina que comenta el problema es de 16 bits. No lo he calculado, pero no me extrañaría que con 16 bits la precisión máxima fuese de, por ejemplo, 2 dígitos... con lo que al tener 0.45, la precisión se va en el 0.4 y las centesimas podrían bailar.

Si con 16 no se reproduce el problema entonces puede que su máquina sea de 8 bits... calcular el margen de error es posible pero no tengo ganas para ponerme calculadora en mano :)
¿De que año es ese libro amgarciac? Porque en informática no es nada recomendable usar material desfasado/anticuado. Por muy bueno que sea.


Título: Re: A un dato de salida se le resta uno sin programarlo así
Publicado por: amgarciac en 24 Julio 2013, 17:14 pm
El libro es de 2006. Por otra parte, aprovecho para responderos a ambos.

Repito que el problema muestra que al usuario le da 0.45 (a nosotros nos da lo correcto: 0.46), y que a raíz de ahí descifremos el error. ¿Es entonces el error debido a codificación binaria, o a qué entonces?


Título: Re: A un dato de salida se le resta uno sin programarlo así
Publicado por: eferion en 24 Julio 2013, 17:19 pm
Para darte una respuesta definitiva tendría que ver el libro, conocer los temas que trata y cómo los trata.


Título: Re: A un dato de salida se le resta uno sin programarlo así
Publicado por: amgarciac en 24 Julio 2013, 17:25 pm
Te dejo un enlace donde puedes hojearlo: http://books.google.es/books?id=OC17arE5xukC&printsec=frontcover&hl=es#v=onepage&q&f=false. El capítulo que aborda esto (así como el que incluye tal relación de problemas) es el 1º, el de introducción.


Título: Re: A un dato de salida se le resta uno sin programarlo así
Publicado por: amgarciac en 19 Agosto 2013, 15:47 pm
Al final descubrí la causa del error: el truncamiento de los decimales sin redondear a pesar de que se leyera uno más (.999999). El error era exclusivo en G++.

Gracias a todos por vuestras respuestas.
Un saludo