2010-06-27 15 views
15

Tal vez, es una pregunta muy simple pero no pude obtener la respuesta. He estado buscando un buen tiempo (ahora Google piensa que estoy enviando consultas automatizadas http://twitter.com/michaelsync/status/17177278608) ..C++ float to int

int n = 4.35 *100; 
cout << n; 

¿Por qué se convierten en la salida "434" en lugar de "435"? 4.35 * 100 = 435 que es un valor entero y esto debería ser asignable a la variable entera "n", ¿verdad?

O ¿El compilador de C++ emite 4.35 enteros antes de multiplicar? Creo que no. ¿Por qué el compilador cambia automáticamente 4.35 a 4.34 que sigue siendo un flotador?

Gracias.

+3

¿Cómo sería el resultado de 434 si 4.35 se convierte en un 'int' antes de la multiplicación? ¿No sería eso 400? Solo para descartar una de tus explicaciones. – pmr

+0

si lo hizo 'int y = (int) (4.35 * 100);' no lo haría; si va a llamar a una función, puede elegir una adecuada para obtener la respuesta que necesita, que también podría hacer en C++. Pero en el código de ejemplo no está llamando a una función, está utilizando la conversión de tipo implícita proporcionada por el idioma. –

+2

4.35 no es exactamente representable. El siguiente valor doble más cercano parece ser (en su caso) 4.34999 ... que, multiplicado por 100, da como resultado 434.999 ... y por lo tanto se convierte en 434. – sellibitze

Respuesta

36

What Every Computer Scientist Should Know About Floating-Point Arithmetic

eso es realmente sólo un punto de partida, por desgracia, como entonces idiomas introducen sus propias debilidades en cuanto a cuando lo hacen conversiones de tipos, etc. En este caso, simplemente ha creado una situación en la que la constante de 4.35 puede 't se representará con precisión, y por lo tanto 4.35 * 100 es más como 434.9999999999, y el elenco a int hace trunc, no round.

+0

¿Está solo en C++? No ocurre en C# .. int n = Convert.ToInt32 (4.35 * 100); Console.WriteLine (n); –

+0

Sucede en C# si lanzas, pero no estás lanzando - ToInt32 rondas (como lo indica muy claramente en la documentación). También podrías redondear en C++ (bueno, 'piso' o' ceil' pero agregar/restar 0.5 para hacer que sea una función de redondeo) –

+0

Bien ... Lo tengo ... gracias .. –

2

La representación interna de 4.35 termina siendo 4.349999999 o similar. Al multiplicar por 100, se desplaza el decimal y se deja caer el .9999 (truncado) al convertir a int.

Editar: Estaba buscando el enlace que Nick publicó. :)

7

Si se ejecuta esta sentencia:

cout << 4.35 

dólares a las rosquillas se obtiene algo aproximadamente como 4,3499998821 debido a 4.35 no es exactamente representable en un flotador.

Cuando el compilador lanza un flotante a un int, se trunca.

Para obtener el comportamiento de su esperada, pruebe:

int n = floor((4.35 * 100.0) + 0.5);

(El trickyness con floor es debido a que C++ no tiene una función nativa round())

0

números de punto flotante don't work that way. Muchos (la mayoría, técnicamente un número infinito de ...) valores no pueden ser almacenados o manipulados precisamente como coma flotante. 4.35 parece ser uno de ellos. Se está almacenando como algo que está realmente por debajo de 4.35, de ahí su resultado.

0

Cuando un float se convierte a un int la parte fraccionaria se trunca, la conversión no toma la int más cercano a la float en valor.

4.35 no se puede representar exactamente como float, el número representable más cercano es (podemos deducir) muy ligeramente menor que 4,35, es decir 4,34999 ..., por lo que cuando se multiplica por 100 que presentamos lo mejor ... 434.999

Si desea convertir un positivo float al int más cercano, debe agregar 0.5 antes de convertirlo a int.

E.g.

int n = (4.35 * 100) + 0.5; 
cout << n;