Comment cela se fait-il dans l'extrait suivant
int a = 7;
int b = 3;
double c = 0;
c = a / b;
c
finit par avoir la valeur 2, plutôt que 2,3333, comme on pouvait s'y attendre. Si a
et b
sont doubles, la réponse passe à 2,333. Mais sûrement parce que c
déjà est un double, il aurait dû fonctionner avec des entiers?
Alors pourquoi int/int=double
ne fonctionne pas?
Réponses:
En effet, vous utilisez la version de division entière de
operator/
, qui prend 2int
s et renvoie unint
. Pour utiliser ladouble
version qui renvoie adouble
, au moins un desint
s doit être explicitement converti en adouble
.la source
a
etb
àdouble
tout simplement pour plus de clarté, mais il n'a pas d' importance.static_cast<>
m'a toujours paru long et essoufflé. Dans le cas des primitives, il n'y a pas vraiment de danger d'obtenirstatic_cast<>
etreinterpret_cast<>
en mixte.static_cast
dans ce cas et utiliser plutôt une fonte de style C. Il n'y a aucun avantage à utiliser des transtypages de style C ++ ici et ils encombrent le code beaucoup plus que des casts de style C. La distribution arithmétique est exactement le contexte où les moulages de style C sont parfaitement appropriés et en fait plus appropriés que les autres moulages.double(b)
. Ils ne se rendent pas toujours compte qu'il s'agit d'une conversion, car cela ressemble à un appel de constructeur explicite.C'est ici:
a) La division de deux
int
s effectue toujours une division entière. Ainsi, le résultat dea/b
dans votre cas ne peut être qu'unint
.Si vous voulez garder
a
et enb
tant queint
s, tout en les divisant complètement, vous devez lancer au moins l'un d'entre eux pour doubler:(double)a/b
oua/(double)b
ou(double)a/(double)b
.b)
c
est undouble
, donc il peut accepter uneint
valeur lors de l'affectation: leint
est automatiquement convertidouble
et affecté àc
.c) Rappelez-vous que lors de l'assignation, l'expression à droite de
=
est calculée en premier (selon la règle (a) ci-dessus, et sans tenir compte de la variable à gauche de=
), puis affectée à la variable à gauche de=
(selon ( b) ci-dessus). Je crois que cela complète le tableau.la source
À quelques exceptions près (je ne peux penser qu'à une seule), C ++ détermine la signification entière d'une expression (ou sous-expression) à partir de l'expression elle-même. Ce que vous faites avec les résultats de l'expression n'a pas d'importance. Dans votre cas, dans l'expression
a / b
, il n'y a pasdouble
de vue; tout estint
. Le compilateur utilise donc la division entière. Ce n'est qu'une fois qu'il a le résultat qu'il considère ce qu'il doit en faire et le convertit endouble
.la source
&funcname
dépend du type vers lequel vous la castez.c
est unedouble
variable, mais la valeur qui lui est assignée est uneint
valeur car elle résulte de la division de deuxint
s, ce qui vous donne une "division entière" (en supprimant le reste). Donc, ce qui se passe dans la lignec=a/b
esta/b
est évalué, créant un temporaire de typeint
c
après la conversion en typedouble
.La valeur de
a/b
est déterminée sans référence à son contexte (affectation àdouble
).la source
Lorsque vous divisez deux entiers, le résultat sera un entier, indépendamment du fait que vous le stockiez dans un double.
la source
En langage C ++, le résultat de la sous-expression n'est jamais affecté par le contexte environnant (à quelques rares exceptions près). C'est l'un des principes que le langage suit attentivement. L'expression
c = a / b
contient une sousa / b
- expression indépendante , qui est interprétée indépendamment de tout ce qui se trouve en dehors de cette sous-expression. La langue ne se soucie pas que vous attribuiez ultérieurement le résultat à un fichierdouble
.a / b
est une division entière. Tout le reste n'a pas d'importance. Vous verrez ce principe suivi dans de nombreux coins de la spécification du langage. Voilà comment fonctionne C ++ (et C).Un exemple d'exception que j'ai mentionné ci-dessus est l'affectation / l'initialisation du pointeur de fonction dans les situations de surcharge de fonction
Il s'agit d'un contexte où le côté gauche d'une affectation / initialisation affecte le comportement du côté droit. (De plus, l'initialisation de la référence au tableau empêche la décroissance du type de tableau, ce qui est un autre exemple de comportement similaire.) Dans tous les autres cas, le côté droit ignore complètement le côté gauche.
la source
L'
/
opérateur peut être utilisé pour la division entière ou la division en virgule flottante. Vous lui donnez deux opérandes entiers, donc il fait une division entière, puis le résultat est stocké dans un double.la source
C'est techniquement une langue dépendante, mais presque toutes les langues traitent ce sujet de la même manière. Lorsqu'il y a une incompatibilité de type entre deux types de données dans une expression, la plupart des langages essaieront de convertir les données d'un côté de
=
pour qu'elles correspondent aux données de l'autre côté selon un ensemble de règles prédéfinies.Lorsque vous divisez deux nombres du même type (entiers, doubles, etc.), le résultat sera toujours du même type (donc «int / int» donnera toujours int).
Dans ce cas, vous avez
double var = integer result
qui convertit le résultat entier en un double après le calcul, auquel cas les données fractionnaires sont déjà perdues. (la plupart des langages effectueront cette conversion pour éviter les inexactitudes de type sans déclencher d'exception ou d'erreur).Si vous souhaitez conserver le résultat comme un double, vous allez vouloir créer une situation où vous avez
double var = double result
Le moyen le plus simple de le faire est de forcer l'expression du côté droit d'une équation à doubler:
c = a/(double)b
La division entre un entier et un double résultera en un transtypage de l'entier en double (notez qu'en faisant des maths, le compilateur "va souvent" vers le type de données le plus spécifique, ceci afin d'éviter la perte de données).
Après l'upcast,
a
terminera comme un double et maintenant vous avez la division entre deux doubles. Cela créera la division et l'affectation souhaitées.ENCORE, veuillez noter que cela est spécifique au langage (et peut même être spécifique au compilateur), cependant presque tous les langages (certainement tous ceux auxquels je peux penser par le haut de ma tête) traitent cet exemple de la même manière.
la source
L'important est que l'un des éléments du calcul soit de type float-double. Ensuite, pour obtenir un double résultat, vous devez lancer cet élément comme indiqué ci-dessous:
ou c = a / static_cast (b);
Ou vous pouvez le créer directement:
Notez que l'un des éléments de calcul doit avoir le '.0' pour indiquer une division d'un type float-double par un entier. Sinon, bien que la variable c soit un double, le résultat sera également nul.
la source