¿Por qué dividir dos int no produce el valor correcto cuando se asigna a double?

5 minutos de lectura

¿Por que dividir dos int no produce el valor correcto
Jahoe

¿Cómo es que en el siguiente fragmento

int a = 7;
int b = 3;
double c = 0;
c = a / b;

c termina teniendo el valor 2, en lugar de 2.3333, como cabría esperar. Si a y b son dobles, la respuesta se convierte en 2.333. Pero seguramente porque c ya es un doble debería haber funcionado con números enteros?

Entonces, ¿cómo es que int/int=double no funciona?

  • El posible duplicado del resultado de la división siempre es cero

    – phuclv

    9 de septiembre de 2018 a las 4:51

Esto se debe a que está utilizando la versión de división entera de operator/que toma 2 ints y devuelve un int. Para usar el double versión, que devuelve un doubleal menos uno de los ints debe convertirse explícitamente en un double.

c = a/(double)b;

  • Preferiría convertir explícitamente ambos a y b para double simplemente por claridad, pero realmente no importa.

    – John Dibling

    27/09/2011 a las 15:31


  • Dado que la pregunta está etiquetada como C++, preferiría ver static_cast<> en lugar de C cast.

    – Martín York

    27 de septiembre de 2011 a las 15:41

  • Personalmente, creo que las conversiones de estilo C son más claras (la conversión en la mayoría de los otros lenguajes comunes se realiza en forma de estilo C). static_cast<> siempre me ha parecido prolijo. En el caso de los primitivos, no hay realmente ningún peligro de obtener static_cast<> y reinterpret_cast<> mezclado.

    – Chad La Guardia

    27 de septiembre de 2011 a las 15:47

  • @Tux-D: ¿Para modelos aritméticos? preferiría evitar static_cast en este caso, use el molde de estilo C en su lugar. No hay ningún beneficio en el uso de moldes de estilo C++ aquí y abarrotan el código mucho más que los moldes de estilo C. El molde aritmético es exactamente el contexto en el que los moldes de estilo C son perfectamente apropiados y, de hecho, más apropiados que otros moldes.

    – Ant

    27 de septiembre de 2011 a las 16:14


  • A veces puedes burlar a la gente “sin estilo C” escribiendo double(b). No siempre se dan cuenta de que se trata de una conversión, ya que se parece a una llamada de constructor explícita.

    –Steve Jessop

    27 de septiembre de 2011 a las 16:26

Aquí lo tienes:

a) Dividiendo dos ints siempre realiza divisiones enteras. Entonces el resultado de a/b en tu caso solo puede ser un int.

Si quieres mantener a y b como ints, sin embargo, divídalos por completo, debe convertir al menos uno de ellos en doble: (double)a/b o a/(double)b o (double)a/(double)b.

B) c es un doublepor lo que puede aceptar un int valor en la cesión: el int se convierte automáticamente en double y asignado a c.

c) Recuerde que en la cesión, la expresión a la derecha de = se calcula primero (de acuerdo con la regla (a) anterior, y sin tener en cuenta la variable a la izquierda de =) y luego asignado a la variable a la izquierda de = (según (b) anterior). Creo que esto completa el cuadro.

Con muy pocas excepciones (solo puedo pensar en una), C++ determina el significado completo de una expresión (o subexpresión) a partir de la expresión misma. Lo que haga con los resultados de la expresión no importa. En tu caso, en la expresión a / bno hay un double visión; todo es int. Entonces el compilador usa la división de enteros. Solo una vez que tiene el resultado, considera qué hacer con él y lo convierte en double.

  • La única excepción en la que puedo pensar es elegir una sobrecarga de función al tomar un puntero: el valor de &funcname depende de a qué tipo lo emitas.

    –Steve Jessop

    27 de septiembre de 2011 a las 15:44


  • @Steve Jessop Esa es la única excepción en la que también puedo pensar. (Pero dado el tamaño y la complejidad del estándar, no me gustaría jurar que no me he perdido ninguno).

    – James Kanze

    27 de septiembre de 2011 a las 16:01

Cuando divide dos números enteros, el resultado será un número entero, independientemente del hecho de que lo almacene en un doble.

c es un double variable, pero el valor que se le asigna es un int valor porque resulta de la división de dos ints, lo que le da una “división de enteros” (dejando de lado el resto). Entonces, ¿qué sucede en la línea? c=a/b es

  1. a/b se evalúa, creando un temporal de tipo int
  2. el valor del temporal se asigna a c después de la conversión a tipo double.

El valor de a/b se determina sin referencia a su contexto (asignación a double).

¿Por que dividir dos int no produce el valor correcto
Hormiga

En el lenguaje C++, el resultado de la subexpresión nunca se ve afectado por el contexto circundante (con algunas raras excepciones). Este es uno de los principios que el lenguaje sigue cuidadosamente. La expresion c = a / b contiene de una subexpresión independiente a / b, que se interpreta independientemente de cualquier cosa fuera de esa subexpresión. Al lenguaje no le importa que luego asignes el resultado a un double. a / b es una división entera. Cualquier otra cosa no importa. Verá que este principio se sigue en muchos rincones de la especificación del lenguaje. Así es como funciona C++ (y C).

Un ejemplo de una excepción que mencioné anteriormente es la asignación/inicialización del puntero de función en situaciones con sobrecarga de funciones

void foo(int);
void foo(double);

void (*p)(double) = &foo; // automatically selects `foo(fouble)`

Este es un contexto donde el lado izquierdo de una asignación/inicialización afecta el comportamiento del lado derecho. (Además, la inicialización de referencia a matriz evita el decaimiento del tipo de matriz, que es otro ejemplo de comportamiento similar). En todos los demás casos, el lado derecho ignora por completo el lado izquierdo.

¿Por que dividir dos int no produce el valor correcto
vicky

los / El operador se puede utilizar para la división de enteros o la división de punto flotante. Le estás dando dos operandos enteros, por lo que está haciendo una división entera y luego el resultado se almacena en un doble.

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad