¿Es lo mismo un Cast que un Convert?

¡A ver los listos!

 

¿Me dicen una diferencia entre hacer un cast o aplicar la clase Convert?

 

Pues hay una que parece muy “sutil” pero que en programas que necesiten cálculos matemáticos exactos  son críticas.

 

Podemos hace esto:

float f = ...

int i = (int) f;

 

O también podemos hacer esto otro.

float f = ...

int i = Convert.ToInt32(f);

 

¡Pero miren los resultados!

 

float

 (int) cast en C#

Convert.ToInt(float)

4.1

4

4

4.5

4

4

5.5

5

6

 

Conclusiones: Mientras el cast trunca, el convert redondea.

Seguro que más de uno está pensando si no ha metido la pata alguna vez con este tema.

¡Saludos!

Archivado en: ,,

Comentarios

# DavidSalgado said:

Parece que el primer tipo de cast utiliza el redondeo común y por eso lo deja en 5, mientras qeu convert utiliza un redondeo gausiano (de banquero) y por eso lo pasa a 6.

Lo curioso es que he hechado un ojo al Convert.ToInt32 de .net 2.0 y .net 1.1......y sorpresa!

Tras una comprobación de si el numero se pasaría del rango de int32..lo que hace es    "return (int) value;"

aqui hay para pergarse un rato a ver que pasa :)

Sunday, December 03, 2006 12:59 PM
# sgolivernet said:

Hombre, el señor Miguel Angel Ramos, hay que ver a las personas que se encuentra uno por estos RSS de dios... qué cantidad de buena gente hemos salido de esa ETSII... :)

Que te vaya bien con tu nuevo blog, te leeré, y no te pongas tan "pejiguera", que un redondeo es un redondeo y no hay que darle más vueltas :)

Salva.

Sunday, December 03, 2006 1:59 PM
# Miguel Angel Ramos said:

Gracias David,

Usando el Reflector me encuentro con el siguiente algoritmo:

public static int ToInt32(double value)

{

     if (value >= 0)

     {

           if (value < 2147483647.5)

           {

                 int num1 = (int) value;

                 double num2 = value - num1;

                 if ((num2 > 0.5) || ((num2 == 0.5) && ((num1 & 1) != 0)))

                 {

                       num1++;

                 }

                 return num1;

           }

     }

     else if (value >= -2147483648.5)

     {

           int num3 = (int) value;

           double num4 = value - num3;

           if ((num4 < -0.5) || ((num4 == -0.5) && ((num3 & 1) != 0)))

           {

                 num3--;

           }

           return num3;

     }

     throw new OverflowException(Environment.GetResourceString("Overflow_Int32"));

}

Como bien dices hace un redondeo al número despues de transformarlo y por eso el efecto distinto entre Convert y el casting.

Saludos!

Sunday, December 03, 2006 2:21 PM
# DavidSalgado said:

Parece que no iba desencaminado pero me colé de función :D

gracias!

Sunday, December 03, 2006 2:41 PM
# Unai said:

La conversion de Convert es realmente el redondeo estándard de la IEEE, algo que no nos enseñan en la escuela porque es más dificil de comprender, que se realiza distinguiendo los pares de los impares ( los impares lo sube y el par lo baja ) cuando la cantidad a redondear está en el punto medio, de esta forma es mucho más equitativo el redondeo puesto que la mitad de los numeros subirían y la otra mitad bajarían ( se supone que existe la misma cantidad de numeros pares que impares) en cambio con el casting lo único que haces es descartar la parte decimal, sea cual sea..

Interesante, sobre estos temas hay cantidad de juegos, os pongo uno, poner un double a 0.1 y un blucle que los sume 100 veces ¿ cual es el resultado ? ¿ por que ?

Monday, December 04, 2006 12:32 AM
# Miguel Angel Ramos said:

Muy bien, manos a la obra:

using System;

namespace JuegoDeUnai

{

   class Program

   {

       static void Main(string[] args)

       {

           double numero = 0.1;

           double resultado = 0;

           for(int i=0;i<100;i++)

           {

               resultado += numero;

           }

           Console.WriteLine(resultado);

           Console.ReadLine();

       }

   }

}

Da un resultado de 9.99999999999998. Eso sólo puede ocurrir porque el algorirmo de sumar esté mal..cosa que estoy seguro que no es así.

Como no puedo ver la implementación de float64, ya que es un tipo del IL, tendré que deducirlo.

Y lo único que se me ocurre es algún problema de optimazación con los floats. Como sé que Unai es matemático, seguro que tiene que ser algo de númoros, así que seguro que han usado alguna base distinta a 10 para hacer operaciones lo más rápidamente posible (como muy común en las arquitecturas de los ordenadores, en las ALU) y ahí la han "cagao".

No obstane...ilumíname Unai!

Monday, December 04, 2006 1:39 AM
# Luis Ruiz Pavón said:

Aqui tienes un artículo que escribió Sergio Tarrillo acerca de esto:

http://geeks.ms/blogs/sergiotarrillo/archive/2006/10/20/4900.aspx

Salu2.

Monday, December 04, 2006 8:13 AM
# Miguel Angel Ramos said:

¡Juas! ¡He acertado! Unai, me debes una cerveza.

Muchas gracias Luis.

Monday, December 04, 2006 11:14 AM
# Unai said:

Muu bien, te pago la cervecita la próxima vez que nos veamos, que estoy seguro que será en el OpenDay!!! Por cierto dentro de poco tendremos en geeks un blog esclusívamente para estos tipos de juegos .... estoy seguro que será divertidísimo...

Saludos

Unai

Monday, December 04, 2006 1:40 PM

Deja tu comentario

(requerido) 
(requerido) 
(opcional)
(requerido)