2010-03-31 15 views
11

Codifiqué algunas cosas de cálculo (copié debajo de un ejemplo realmente simplificado de lo que hice) como CASE2 y obtuve malos resultados. Refactorizado el código como CASE1 y funcionó bien. Sé que hay un elenco implícito en CASO 2, pero no estoy seguro del motivo completo. Cualquiera me podría explicar lo que está pasando exactamente debajo?Explicación de conversión/conversión int/double en C#

//CASE 1, result 5.5 
    double auxMedia = (5 + 6); 
    auxMedia = auxMedia/2; 

    //CASE 2, result 5.0 
    double auxMedia1 = (5 + 6)/2; 

    //CASE 3, result 5.5 
    double auxMedia3 = (5.0 + 6.0)/2.0; 

    //CASE 4, result 5.5 
    double auxMedia4 = (5 + 6)/2.0; 

Mi suposición es que/2 en CASE2 está lanzando (5 + 6) a int y causando ronda de división a 5, a continuación fundido de nuevo para doblar y convertido a 5,0.

CASE3 y CASE 4 también solucionan el problema.

+2

Como nota al margen; solo hay * una * operación realizada en tiempo de ejecución aquí. El '/ 2' en el caso 1. El resto lo hace el compilador. –

+0

@Marc: ¿no puede el compilador incluso realizar el caso 1 completamente en tiempo de compilación, ya que 'auxMedia' es local y se le asigna una constante? ¿O es una optimización que queda estrictamente para el JIT? –

+0

@Michael - Esperaría * que se lo dejara al JIT. Para responderlo, necesitaría ver diferentes salidas del compilador ... –

Respuesta

13
  1. 5 + 6 es un número entero 11; el cual luego se duplicará (en la tarea) y se dividirá por dos; 5.5
  2. 5 + 6 es un número entero 11; número entero 11/2 = bajo aritmética de enteros, que entonces fundido a doble (en la asignación)
  3. 5,0 + 6,0 es el doble de 11,0; dividir por doble 2.0 dando doble 5.5
  4. 5 + 6 es un número entero 11; hay una conversión implícita para duplicar 11.0 para la división, y luego dividir doble 2,0 dando doble 5,5
+0

Marc es correcto. Si su segunda línea era 'auxMedia = auxMedia/2.0', obtendría el resultado esperado, ya que' 2.0' se lee como un doble y '2' se lee como un int (se descarta cualquier dígito decimal - no lo hace incluso alrededor). – Jaxidian

1
//CASE 2, result 5.0 
double auxMedia1 = (5 + 6)/2; 

El resultado de la (5 + 6) operación es entero. Porque ambos operandos son de tipo entero. Luego, el compilador realiza 11/2, donde ambos operandos también son enteros. El resultado de la última división es obviamente 5, porque es una división entera (no se conoce la palabra correcta en inglés).

1

Estás en la correcta. CASO 2 usa la aritmética de enteros hasta que se realice la asignación. También puede solucionar el problema al hacer una conversión explícita:

double auxMedia1 = ((double) (5 + 6))/2; 
5

Para ampliar Marc (correcto) responden un poco, números enteros se interpretan como número entero, mientras que los números con puntos decimales se interpretan como doble. Para declarar un número entero como un doble literal, añadir una "D" a la misma:

 //CASE 2b, result 5.5 
     double auxMedia2b = (5D + 6D)/2;