¿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 era de esperar. Si a
y b
son dobles, la respuesta pasa a 2.333. ¿Pero seguramente porque c
ya es un doble debería haber trabajado con enteros?
Entonces, ¿cómo int/int=double
es que no funciona?
c++
variables
double
integer-division
Jahoe
fuente
fuente
Respuestas:
Esto se debe a que está utilizando la versión de división entera de
operator/
, que tarda 2int
sy devuelve unint
. Para utilizar ladouble
versión, que devuelve adouble
, al menos uno de losint
s debe convertirse explícitamente en adouble
.fuente
a
yb
quedouble
simplemente por claridad, pero realmente no importa.static_cast<>
siempre me pareció largo aliento. En el caso de primitivas, en realidad no hay ningún peligro de conseguirstatic_cast<>
yreinterpret_cast<>
hasta mixto.static_cast
en este caso y usar yeso estilo C. No hay ningún beneficio en el uso de versiones de estilo C ++ aquí y desordenan el código mucho más que las versiones de estilo C. El reparto aritmético es exactamente el contexto en el que los modelos de estilo C son perfectamente apropiados y, en realidad, más apropiados que otros modelos.double(b)
. No siempre se dan cuenta de que es una conversión, ya que se ve igual que una llamada explícita a un constructor.Aquí está:
a) La división de dos
int
s siempre realiza la división de enteros. Entonces, el resultado dea/b
en su caso solo puede ser unint
.Si desea mantener
a
yb
comoint
s, pero dividirlos completamente, debe lanzar al menos uno de ellos para duplicar:(double)a/b
oa/(double)b
o(double)a/(double)b
.b)
c
es undouble
, por lo que puede aceptar unint
valor en la asignación: elint
se convierte automáticamentedouble
y se asigna ac
.c) Recuerde que en la asignació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 se asigna a la variable a la izquierda de=
(según ( b) arriba). Creo que esto completa el cuadro.fuente
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. No importa lo que hagas con los resultados de la expresión. En tu caso, en la expresión
a / b
, no hay undouble
a la vista; todo esint
. Entonces el compilador usa la división de enteros. Solo una vez que tiene el resultado, considera qué hacer con él y lo convierte adouble
.fuente
&funcname
depende del tipo al que lo eches.c
es unadouble
variable, pero el valor que se le asigna es unint
valor porque resulta de la división de dosint
s, lo que le da una "división entera" (descartando el resto). Entonces, lo que pasa en la filac=a/b
esa/b
se evalúa, creando un temporal de tipoint
c
después de la conversión a tipodouble
.El valor de
a/b
se determina sin referencia a su contexto (asignación adouble
).fuente
Cuando divide dos enteros, el resultado será un entero, independientemente del hecho de que lo almacene en un doble.
fuente
En 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 sigue cuidadosamente el lenguaje. La expresión
c = a / b
contiene una subexpresión independientea / b
, que se interpreta independientemente de cualquier cosa fuera de esa subexpresión. Al idioma no le importa que luego le asignes el resultado a undouble
.a / b
es una división entera. Cualquier otra cosa no importa. Verá que este principio se sigue en muchos aspectos 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
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 la caída 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.
fuente
El
/
operador se puede utilizar para la división de enteros o la división de punto flotante. Le está dando dos operandos enteros, por lo que está haciendo una división de enteros y luego el resultado se almacena en un doble.fuente
Técnicamente, esto depende del idioma, pero casi todos los idiomas tratan este tema de la misma manera. Cuando hay una falta de coincidencia de tipos entre dos tipos de datos en una expresión, la mayoría de los lenguajes intentarán convertir los datos en un lado del
=
para hacer coincidir los datos en el otro lado de acuerdo con un conjunto de reglas predefinidas.Al dividir dos números del mismo tipo (enteros, dobles, etc.) el resultado siempre será del mismo tipo (por lo que 'int / int' siempre resultará en int).
En este caso, tiene lo
double var = integer result
que convierte el resultado entero en un doble después del cálculo, en cuyo caso los datos fraccionarios ya se han perdido. (la mayoría de los lenguajes harán esta conversión para evitar imprecisiones de tipo sin generar una excepción o error).Si desea mantener el resultado como el doble, querrá crear una situación en la que tenga
double var = double result
La forma más fácil de hacerlo es forzar la expresión en el lado derecho de una ecuación para que se duplique:
c = a/(double)b
La división entre un entero y un doble resultará en convertir el entero al doble (tenga en cuenta que al hacer matemáticas, el compilador a menudo "convertirá" al tipo de datos más específico, esto es para evitar la pérdida de datos).
Después del upcast,
a
terminará como un doble y ahora tienes una división entre dos dobles. Esto creará la división y asignación deseadas.OTRA VEZ, tenga en cuenta que esto es específico del idioma (e incluso puede ser específico del compilador), sin embargo, casi todos los idiomas (ciertamente todos los que se me ocurren) tratan este ejemplo de manera idéntica.
fuente
Lo importante es que uno de los elementos de cálculo sea del tipo float-double. Luego, para obtener un resultado doble, debe lanzar este elemento como se muestra a continuación:
o c = a / static_cast (b);
O puede crearlo directamente:
Tenga en cuenta que uno de los elementos de cálculo debe tener '.0' para indicar una división de un tipo flotante-doble por un entero. De lo contrario, a pesar de que la variable c sea doble, el resultado también será cero.
fuente