Je veux savoir mieux quand je devrais lancer. Quelles sont les règles de conversion de type implicites en C++ lors de l’ajout, de la multiplication, etc. Par exemple,
int + float = ?
int * float = ?
float * int = ?
int / float = ?
float / int = ?
int / int = ?
int ^ float = ?
etc...
L'expression sera-t-elle toujours évaluée comme type plus précis? Les règles diffèrent-elles pour Java? S'il vous plaît, corrigez-moi si j'ai formulé cette question de manière inexacte.
En C++, les opérateurs (pour les types POD) agissent toujours sur des objets du même type.
Ainsi, s’ils ne sont pas identiques, ils seront promus pour correspondre à l’autre.
Le type du résultat de l'opération est identique à celui des opérandes (après conversion).
If either is long double the other is promoted to long double
If either is double the other is promoted to double
If either is float the other is promoted to float
If either is long long unsigned int the other is promoted to long long unsigned int
If either is long long int the other is promoted to long long int
If either is long unsigned int the other is promoted to long unsigned int
If either is long int the other is promoted to long int
If either is unsigned int the other is promoted to unsigned int
If either is int the other is promoted to int
Both operands are promoted to int
Remarque. La taille minimale des opérations est int
. Donc, short
/char
sont promus à int
avant la fin de l'opération.
Dans toutes vos expressions, int
est promu en tant que float
avant que l'opération soit effectuée. Le résultat de l'opération est un float
.
int + float => float + float = float
int * float => float * float = float
float * int => float * float = float
int / float => float / float = float
float / int => float / float = float
int / int = int
int ^ float => <compiler error>
Les opérations arithmétiques impliquant float
donnent float
.
int + float = float
int * float = float
float * int = float
int / float = float
float / int = float
int / int = int
Pour plus de détails, répondez. Regardez ce que dit la section §5/9 de la norme C++
De nombreux opérateurs binaires qui attendent des opérandes de type arithmétique ou énumération provoquent des conversions et génèrent des types de résultat de la même manière. Le but est de donner un type commun, qui est aussi le type du résultat.
Ce modèle s'appelle les conversions arithmétiques habituelles, définies comme suit:
- Si l'un des opérandes est de type long double, l'autre sera converti en long double.
- Sinon, si l'un des opérandes est double, l'autre sera converti en double.
- Sinon, si l'un des opérandes est float, l'autre doit être converti en float.
- Sinon, les promotions intégrales (4.5) doivent être effectuées sur les deux opérandes.54)
- Ensuite, si l'un des opérandes est long non signé, l'autre doit être converti en long non signé.
- Autrement, si un opérande est un long int et l'autre unsigned int, alors si un long int peut représenter toutes les valeurs d'un unsigned int, il doit être converti en long int; sinon, les deux opérandes doivent être convertis en unsigned long int.
- Sinon, si l'un des opérandes est long, l'autre doit être converti en long.
- Sinon, si l'un des opérandes est non signé, l'autre doit être converti en non signé.
[Note: sinon, le seul cas restant est que les deux opérandes sont int]
Puisque les autres réponses ne parlent pas des règles de C++ 11, en voici une. À partir de la norme C++ 11 (projet n ° 3337) §5/9:
Ce modèle est appelé les conversions arithmétiques usuelles , définies comme suit:
- Si l'un des opérandes est de type énumération étendue, aucune conversion n'est effectuée. si l'autre opérande n'a pas le même type, l'expression est mal formée.
- Si l'un des opérandes est de type long double, l'autre sera converti en long double.
- Sinon, si l'un des opérandes est double, l'autre sera converti en double.
- Sinon, si l'un des opérandes est float, l'autre doit être converti en float.
- Sinon, les promotions intégrales doivent être effectuées sur les deux opérandes. Ensuite, les règles suivantes doivent être appliquées aux opérandes promus:
- Si les deux opérandes ont le même type, aucune conversion supplémentaire n'est nécessaire.
- Sinon, si les deux opérandes ont des types entiers signés ou que les deux ont des types entiers non signés, l'opérande ayant le type de rang de conversion inférieur doit être converti en un type d'opérande de rang supérieur.
- Autrement, si l'opérande de type entier non signé a un rang supérieur ou égal au rang du type de l'autre opérande, l'opérande de type entier signé doit être converti en un type d'opérande de type entier non signé.
- Autrement, si le type de l'opérande avec le type entier signé peut représenter toutes les valeurs du type de l'opérande avec le type entier non signé, l'opérande avec le type entier non signé doit être converti au type de l'opérande avec le type entier signé.
- Sinon, les deux opérandes doivent être convertis en un type entier non signé correspondant au type d'opérande avec un type entier signé.
Voir ici pour une liste fréquemment mise à jour.
Cette réponse s’adresse en grande partie à un commentaire de @ RafałDowgird:
"La taille minimale des opérations est int." - Cela serait très étrange (qu'en est-il des architectures qui supportent efficacement les opérations char/short?) Est-ce vraiment dans les spécifications C++?
Gardez à l'esprit que la norme C++ contient la règle primordiale "comme si". Voir section 1.8: Exécution du programme:
3) Cette disposition est parfois appelée règle "as-if", car une implémentation est libre de ne pas respecter une exigence de la norme tant que le résultat est comme si l'exigence avait été respectée, dans la mesure où elle peut être déterminée à partir de l'observable. comportement du programme.
Le compilateur ne peut pas définir une valeur de int
de 8 bits, même si elle est la plus rapide, car la norme impose un minimum de 16 bits int
.
Par conséquent, dans le cas d’un ordinateur théorique avec des opérations ultra-rapides sur 8 bits, la promotion implicite de int
pour l’arithmétique pourrait avoir de l’importance. Cependant, pour de nombreuses opérations, vous ne pouvez pas savoir si le compilateur a réellement effectué les opérations avec la précision d'un int
puis converti en un char
à stocker dans votre variable, ou si les opérations ont été effectuées en omble tout au long.
Par exemple, considérons unsigned char = unsigned char + unsigned char + unsigned char
, où l’addition déborderait (supposons une valeur de 200 pour chacun). Si vous aviez promu int
, vous auriez 600, qui seraient alors implicitement convertis en un unsigned char
, qui encapsulerait le modulo 256, donnant ainsi un résultat final de 88. Si vous ne faites aucune promotion de ce type, vous devrez encapsuler les deux premiers ajouts, ce qui réduirait le problème de 200 + 200 + 200
à 144 + 200
, qui est 344, ce qui réduit à 88. En d’autres termes, le programme ne connaissant pas la différence, le compilateur est donc libre d’ignorer le mandat permettant d’effectuer des opérations intermédiaires dans int
si les opérandes ont une valeur inférieure. classement que int
.
Ceci est vrai en général pour l'addition, la soustraction et la multiplication. Ce n'est pas vrai en général pour la division ou le module.
Si vous excluez les types non signés, il existe une hiérarchie ordonnée: chars signés, short, int, long, long long, float, double, long double. Tout d’abord, tout ce qui vient avant int dans ce qui précède sera converti en int. Ensuite, dans une opération binaire, le type de rang inférieur sera converti en supérieur et les résultats seront le type du supérieur. (Vous remarquerez que, dans la hiérarchie, chaque fois qu'un type à virgule flottante et un type intégral sont impliqués, le type intégral est converti en type à virgule flottante.)
Unsigned complique un peu les choses: cela perturbe le classement et certaines parties du classement sont définies par la mise en œuvre. Pour cette raison, il est préférable de ne pas mélanger signé et non signé dans la même expression. (La plupart des experts en C++ semblent éviter les signatures non signées, à moins que des opérations au niveau des bits ne soient impliquées. C'est du moins ce que recommande Stroustrup.)
Mon solution au problème obtenu WA (mauvaise réponse), alors j'ai changé l'un des int
en long long int
et il a donné AC (accepter) . Auparavant, j'essayais de faire long long int += int * int
, et après je le corrige en long long int += long long int * int
. Googler je suis venu avec,
Conditions pour la conversion de type:
Conditions remplies ---> Conversion
Chaque opérande est de type long double . ---> L’autre opérande est converti en type long double .
La condition précédente n'est pas remplie et l'un ou l'autre des opérandes est de type double . ---> L’autre opérande est converti en type double .
Les conditions précédentes ne sont pas remplies et l'un des opérandes est de type float . ---> L’autre opérande est converti en type float .
Conditions précédentes non remplies (aucun des opérandes n'est de type flottant). ---> Les promotions intégrales sont effectuées sur les opérandes comme suit:
Les types entiers inférieurs à int sont promus lorsqu'une opération est effectuée sur eux. Si toutes les valeurs du type d'origine peuvent être représentées sous la forme d'un entier, la valeur du type le plus petit est convertie en un entier; sinon, il est converti en un unsigned int. Les promotions entières sont appliquées dans le cadre des conversions arithmétiques habituelles en certaines expressions d'argument. les opérandes des opérateurs unaires +, - et ~; et des opérandes des opérateurs de postes.
Rang de conversion entier:
long long int
doit être supérieur au rang de long int
, qui doit être supérieur au rang de int
, qui doit être supérieur au rang de short int
, qui doit être supérieur au rang de signed char
.char
doit être égal au rang de signed char
et unsigned char
.Conversions arithmétiques habituelles:
Le type de l'expression, lorsque les deux parties ne sont pas du même type, sera converti en le plus grand des deux. Le problème ici est de savoir lequel est le plus gros (c’est différent de la taille en octets).
Dans les expressions dans lesquelles un nombre réel et un nombre entier sont impliqués, le nombre entier sera promu en nombre réel. Par exemple, dans int + float, le type de l'expression est float.
L'autre différence est liée à la capacité du type. Par exemple, une expression impliquant un int et un long int résultera du type long int.
Tout le chapitre 4 parle de conversions, mais je pense que vous devriez vous intéresser principalement à celles-ci:
4.5 promotions intégrales [conv.prom]
Une rvalue de type char, char signée, unsigned char, short int ou unsigned short int peut être convertie en une rvalue de type int si int peut représenter toutes les valeurs du type source; autre-
sage, la rvalue source peut être convertie en une rvalue de type unsigned int.
Une rvalue de type wchar_t (3.9.1) ou un type d’énumération (7.2) peut être convertie en une rvalue de la première
des types suivants pouvant représenter toutes les valeurs de son type sous-jacent: int, unsigned int,
long ou non signé longtemps.
Une valeur pour un champ de bits intégral (9.6) peut être convertie en une valeur de type int si int peut représenter tous les éléments.
les valeurs du champ de bits; sinon, il peut être converti en unsigned int si unsigned int peut
a renvoyé toutes les valeurs du champ de bits. Si le champ de bits est encore plus grand, aucune promotion intégrale ne lui est appliquée. Si la
le champ de bits a un type énuméré, il est traité comme toute autre valeur de ce type à des fins de promotion.
Une valeur de type bool peut être convertie en une valeur de type int, false devenant nul et vrai
en devenir un.
Ces conversions sont appelées promotions intégrales.
4.6 Promotion en virgule flottante [conv.fpprom]
Une valeur de type float peut être convertie en une valeur de type double. La valeur est inchangée.
Cette conversion s'appelle promotion en virgule flottante.
Par conséquent, toutes les conversions impliquant float - le résultat est float.
Seul celui impliquant les deux int - le résultat est int: int/int = int