Quiero ser mejor sobre saber cuándo debo lanzar. ¿Cuáles son las reglas de conversión de tipo implícito en C ++ al agregar, multiplicar, etc. Por ejemplo,
int + float = ?
int * float = ?
float * int = ?
int / float = ?
float / int = ?
int / int = ?
int ^ float = ?
etcétera...
¿Se evaluará siempre la expresión como el tipo más preciso? ¿Las reglas difieren para Java? Corríjame si he formulado esta pregunta de manera incorrecta.
^
es XOR.Respuestas:
En C ++, los operadores (para los tipos de POD) siempre actúan sobre objetos del mismo tipo.
Por lo tanto, si no son iguales, se promoverá uno para que coincida con el otro.
El tipo del resultado de la operación es el mismo que el de los operandos (después de la conversión).
Nota. El tamaño mínimo de las operaciones es
int
. Entoncesshort
/char
son promovidos aint
antes de que se realice la operación.En todas sus expresiones,
int
se promueve afloat
antes de que se realice la operación. El resultado de la operación es afloat
.fuente
char
. Si el valor dechar + char
se asigna a achar
, entonces solo puede hacer la aritméticachar
y, por ejemplo, ajustar. Pero si se asigna el resultado,int
entonces tiene que hacer la aritmética en un tipo lo suficientemente grande como para obtener el resultado correcto cuando es más queCHAR_MAX
.((int) 4) - ((unsigned int) 5)
dará como resultado4294967295
entradas de 32 bits y entradas de 32 bits sin signo.Operaciones aritméticas que implican
float
resultados enfloat
.Para más detalles responda. Mire lo que dice la sección §5 / 9 del Estándar C ++
fuente
double
tampocolong double
.long long
yunsigned long
no se aborda aquí.float
no tiene suficientes bits en la mantisa (24 bits para IEEE-754 ) para un 32 bitsint
, por lo que puede haber alguna pérdida de datos. Un 64 bitsdouble
debería estar bien.Como las otras respuestas no hablan sobre las reglas en C ++ 11, aquí hay una. Del estándar C ++ 11 (borrador n3337) §5 / 9 (enfatizó la diferencia):
Vea aquí una lista que se actualiza con frecuencia.
fuente
Esta respuesta está dirigida en gran parte a un comentario hecho por @ RafałDowgird:
Tenga en cuenta que el estándar C ++ tiene la importante regla "como si". Ver sección 1.8: Ejecución del programa:
El compilador no puede establecer un
int
tamaño de 8 bits, incluso si fuera el más rápido, ya que el estándar exige un mínimo de 16 bitsint
.Por lo tanto, en el caso de una computadora teórica con operaciones súper rápidas de 8 bits, la promoción implícita
int
de aritmética podría ser importante. Sin embargo, para muchas operaciones, no puede saber si el compilador realmente realizó las operaciones con la precisión de anint
y luego se convirtió en achar
para almacenar en su variable, o si las operaciones se realizaron en char todo el tiempo.Por ejemplo, considere
unsigned char = unsigned char + unsigned char + unsigned char
dónde se desbordaría la suma (supongamos un valor de 200 para cada uno). Si ascendieras aint
, obtendrías 600, que luego se convertirían implícitamente en ununsigned char
, que envolvería el módulo 256, dando así un resultado final de 88. Si no hicieras tales promociones, tendrías que envolver entre el primer dos adiciones, lo que reduciría el problema de200 + 200 + 200
a144 + 200
, que es 344, que se reduce a 88. En otras palabras, el programa no conoce la diferencia, por lo que el compilador es libre de ignorar el mandato de realizar operaciones intermediasint
si los operandos tienen una clasificación más baja queint
.Esto es cierto en general de suma, resta y multiplicación. No es cierto en general para la división o el módulo.
fuente
Si excluye los tipos sin firmar, hay una jerarquía ordenada: char firmado, short, int, long, long long, float, double, long double. Primero, todo lo que venga antes de int en lo anterior se convertirá a int. Luego, en una operación binaria, el tipo de clasificación inferior se convertirá en el superior y los resultados serán del tipo superior. (Notará que, desde la jerarquía, cada vez que intervienen un punto flotante y un tipo integral, el tipo integral se convertirá al tipo de punto flotante).
Unsigned complica un poco las cosas: perturba la clasificación y partes de la clasificación se definen como implementación. Debido a esto, es mejor no mezclar con y sin signo en la misma expresión. (La mayoría de los expertos en C ++ parecen evitar sin firmar a menos que estén involucradas operaciones bit a bit. Al menos, eso es lo que recomienda Stroustrup).
fuente
int
para un número que nunca necesita ser negativo es un desperdicio completo de un 50% del rango disponible. Ciertamente no soy Stroustrup, pero lo usounsigned
por defecto ysigned
solo cuando tengo una razón.bool in_order(vector<T> vec) { for ( int i = 0; i < size() - 1; ++i) { if (vec[i + 1] < vec[i]) return false; } return true;
y luego se molestaría al descubrir que se bloquea por vectores vacíos porque size () - 1 devuelve 18446744073709551615.Mi solución al problema tiene WA (respuesta incorrecta), entonces me cambió uno de
int
along long int
y se la dio CA (aceptar) . Anteriormente, estaba tratando de hacerlolong long int += int * int
, y luego lo rectificolong long int += long long int * int
. Google se me ocurrió,1. Conversiones aritméticas
Condiciones para la conversión de tipo:
Condiciones cumplidas ---> Conversión
Cualquiera de los operandos es de tipo largo doble . ---> Otro operando se convierte a tipo largo doble .
Condición anterior no cumplida y cualquiera de los operandos es de tipo doble . ---> Otro operando se convierte al tipo double .
No se cumplen las condiciones anteriores y cualquiera de los operandos es de tipo flotante . ---> Otro operando se convierte a tipo flotante .
Condiciones anteriores no cumplidas (ninguno de los operandos son de tipo flotante). ---> Las promociones integrales se realizan en los operandos de la siguiente manera:
2) Reglas de conversión de enteros
Los tipos enteros más pequeños que int se promueven cuando se realiza una operación en ellos. Si todos los valores del tipo original se pueden representar como un int, el valor del tipo más pequeño se convierte en un int; de lo contrario, se convierte en un int sin signo. Las promociones de enteros se aplican como parte de las conversiones aritméticas habituales a ciertas expresiones de argumento; operandos de los operadores unarios +, - y ~; y operandos de los operadores de turno.
Rango de conversión de enteros:
long long int
será mayor que el rango delong int
, que será mayor que el rango deint
, que será mayor que el rango deshort int
, que será mayor que el rango designed char
.char
será igual al rango designed char
yunsigned char
.Conversiones aritméticas habituales:
fuente
Todo el capítulo 4 habla sobre las conversiones, pero creo que debería interesarle principalmente:
4.5 Promociones integrales [conv.prom]
Un valor r de tipo char, char firmado, unsigned char, short int o unsigned short int se puede convertir en un rvalue de tipo int si int puede representar todos los valores del tipo fuente; de lo
contrario, el valor r de origen se puede convertir a un valor r de tipo unsigned int.
Un valor r de tipo wchar_t (3.9.1) o un tipo de enumeración (7.2) se puede convertir en un valor r del primero
de los siguientes tipos que puede representar todos los valores de su tipo subyacente: int, unsigned int,
long o unsigned largo.
Un valor r para un campo de bits integral (9.6) se puede convertir en un valor r de tipo int si int puede representar todos
los valores del campo de bits; de lo contrario, se puede convertir a unsigned int si unsigned int puede repetir
reenviar todos los valores del campo de bits. Si el campo de bits es aún mayor, no se aplica ninguna promoción integral. Si el
campo de bits tiene un tipo enumerado, se trata como cualquier otro valor de ese tipo para fines de promoción.
Un valor de tipo bool se puede convertir en un valor de tipo int, con falso convirtiéndose en cero y verdadero
convirtiéndose en uno.
Estas conversiones se llaman promociones integrales.
4.6 Promoción de punto flotante [conv.fpprom]
Un valor de tipo flotante se puede convertir en un valor de tipo doble. El valor no ha cambiado.
Esta conversión se llama promoción de punto flotante.
Por lo tanto, todas las conversiones que involucran flotante - el resultado es flotante.
Solo el que involucra ambos int: el resultado es int: int / int = int
fuente
El tipo de la expresión, cuando no ambas partes son del mismo tipo, se convertirá en la mayor de ambas. El problema aquí es entender cuál es más grande que la otra (no tiene nada que ver con el tamaño en bytes).
En las expresiones en las que están involucrados un número real y un número entero, el número entero será promovido a número real. Por ejemplo, en int + float, el tipo de expresión es float.
La otra diferencia está relacionada con la capacidad del tipo. Por ejemplo, una expresión que involucra un int y un int largo resultará del tipo long int.
fuente
long
es "más grande" que afloat
pero ¿cuál es el tipo delong
+float
?¡Consideración!
Las conversiones ocurren de izquierda a derecha.
Prueba esto:
fuente
j + i * k
daría como resultado 101.