7
votes

Integer VS Division flottante -> Qui est responsable de fournir le résultat?

Je suis programmée pendant un certain temps en C ++, mais soudainement eu un doute et voulait préciser avec la communauté Stackoverflow.

Lorsqu'un entier est divisé par un autre entier, nous savons tous que le résultat est un entier et comme sage, un flotteur divisé par le flotteur est également un flotteur.

Mais qui est responsable de fournir ce résultat? Est-ce le compilateur ou l'instruction DIV?


1 commentaires

Est-ce que vous divisez les constantes ou les variables?


6 Réponses :


12
votes

Cela dépend de la question de savoir si votre architecture a a div instruction. Si votre architecture dispose des instructions de division d'entiers et de points flottants, le compilateur émettra la bonne instruction pour le cas spécifié par le code. La norme linguistique spécifie les règles de promotion de type et si la division entier ou en inteir doit être utilisée dans chaque situation possible.

Si vous n'avez qu'une instruction de division entier, ou uniquement une instruction de division de points flottants, le compilateur sera conforme à un code ou générera un appel à une bibliothèque de support mathématique pour gérer la division. Les instructions de division sont notoirement lentes, la plupart des compilateurs tenteront de les optimiser si possible (par exemple, remplacez-les par des instructions de décalage ou de précalculer le résultat pour une division des constantes de compilation).


0 commentaires

3
votes

Le compilateur décidera au moment de la compilation Quelle forme de division requise en fonction des types de variables utilisées - à la fin de la journée, une instruction DIV (ou FDIV) d'une forme ou d'une autre s'impliquera.


2 commentaires

Sauf si les variables sont des constantes de la compilation, auquel cas le compilateur «assumera la responsabilité» et aucune instruction n'est produite.


@Potatoswatter: Pas entièrement vrai; Le compilateur doit évaluer les expressions constantes intégrées et peut évaluer d'autres expressions constantes. C'est à dire. Float X = 1.0 / 3.0 peut être évalué par le compilateur ou peut aboutir à un choix de FDIV-Compiler.



3
votes

Les instructions de division matérielle n'incluent presque jamais la conversion entre le point entier et le point flottant. Si vous obtenez des instructions de division du tout (ils sont parfois laissés de côté, car un circuit de division est large et compliqué), ils sont pratiquement certains d'être «Divisez-le par INT, produisent int» et «diviser le flotteur par flotteur, produisent du flotteur» . Et ce sera généralement que les entrées et la sortie sont toutes de la même taille.

Le compilateur est responsable de la construction de toute opération écrite dans le code source, au-dessus de ces primitives. Par exemple, en C, si vous divisez un float par une INT, le compilateur émettra une conversion into-float puis une fracture de flotteur.

(existent farfely existent. Je ne sais pas, mais je ne le mettrais pas au-delà du VAX d'avoir eu des instructions de type "diviser par int". L'itanium n'a pas vraiment eu une instruction de division, mais sa "Diviser Helper" était seulement pour un point flottant, vous avez dû fake faux diviser au-dessus de la fracture de flotteur!)


3 commentaires

Il h. En ce qui concerne les "exceptions négligentes", comme vous les appelez, vous avez probablement utilisé une seule maintenant pour écrire cette réponse. L'instruction X86 (ou plus précisément x87) pour Diviser Float par Int est appelée Fidiv.


Et ce n'est pas le seul point où la farce de X86 met la honte de Vax :).


Hah! Eh bien, ce serait le x87. Ils n'ont pas fait rien la voie normale avec cette chose.



0
votes

pratiquement

la norme C99 définit "lorsque les entiers sont divisés, le résultat de l'opérateur est le quotient algébrique avec une partie fractionnelle mis au rebut. "Et ajoute dans une note de bas de page qui" ceci est souvent appelée "troncature vers zéro" "

Historique

Historiquement, la spécification de la langue est responsable.

Pascal Définit sa opérateurs de sorte qu'utiliser / pour la division renvoie toujours un réel (même si vous l'utilisez pour diviser 2 entiers), et si vous voulez diviser les entiers et obtenir Un résultat entier, vous utilisez l'opérateur div à la place. (Visual Basic a une distinction similaire et utilise l'opérateur \ pour la division entière qui renvoie un résultat entier.)

En C, il a été décidé que la même distinction doit être faite en casting l'un des opérandes entier à un float si vous vouliez un résultat de point flottant. Il est devenu convention de traiter des types de points entier par rapport à la manière dont vous décrivez dans de nombreuses langues dérivées de C. Je soupçonne que cette convention peut être originaire de Fortran.


0 commentaires

1
votes

L'une des règles les plus importantes de la norme C ++ est la règle "comme si" la règle:

Les descriptions sémantiques de cette norme internationale définissent une machine abstraite non déterministe paramétrée. Cette norme internationale n'entre aucune exigence sur la structure des implémentations conformes. En particulier, ils n'ont pas besoin de copier ou d'émuler la structure de la machine abstraite. Des implémentations conformes sont plutôt nécessaires pour émuler (uniquement) le comportement observable de la machine abstraite comme expliqué ci-dessous.

Qui par rapport à votre question signifie que cela n'a pas d'importance à quelle composante la division est-elle aussi longue que celle-ci. Il peut être effectué par un code de machine div , il peut être effectué par un code plus compliqué s'il n'y a pas d'instruction appropriée pour le processeur en question.

Il peut aussi:

  1. Remplacez l'opération par une opération de décalage bit si approprié et susceptible d'être plus rapide.
  2. Remplacez l'opération par un littéral si calculable au moment de la compilation ou une affectation si par exemple. Lors du traitement X / Y, il peut être affiché au moment de la compilation que Y sera toujours 1.
  3. Remplacez l'opération par un lancer d'exception si elle peut être affichée lors de la compilation de la compilation qu'il s'agira toujours d'une division entière par zéro.

5 commentaires

Pourrait-il refuser de compiler s'il pouvait déduire au moment de la compilation que le quotient serait toujours zéro ou est-il légitime pour un programme C entièrement conforme de contenir une instruction comme x = 1 / (x-x); à condition qu'une telle instruction n'exécute jamais réellement?


@supercat: C'est parfaitement légitime. C'est l'exécution d'une division par zéro qui provoque un comportement indéfini.


@supercat Si vous souhaitez produire un programme qui a toujours des erreurs, c'est votre entreprise! Il est difficile d'apprendre aux gens des erreurs sans eux (bien que dans certaines langues, vous devez faire des trucs comme si (vrai == faux) Pour tromper les compilateurs en vous laissant compiler). Il serait certainement raisonnable et utile que le compilateur produit un avertissement non normalisé.


... L'important est que si un expert infaillible sur la langue indique ", il se comportera donc" alors il doit faire ce que l'expert dit comme vu de l'extérieur. Comment cela fait-il que c'est au compilateur. Ces bits qui sont "indéfinis" sont où l'expert dira "Je ne sais pas ce que ça va faire" (En réalité, il va probablement expliquer le mauvais code, vous savez quels experts sont comme), mais défini uniquement s'applique à "à l'extérieur "Vues. Cela est important pour permettre des optimisations et une grande partie de la STL dépend de cela pour ne pas vraiment sucer les termes de performance.


Le compilateur peut également remplacer x / 2.5 avec x * 0.4 . Ceci est en fait commun car la multiplication est souvent plus rapide que la division.



2
votes

Votre question n'a pas vraiment de sens. L'instruction DIV ne fait pas rien par lui-même. Peu importe la taille que vous criez, même si vous essayez de le corrompre, cela ne prend pas la responsabilité de rien

Lorsque vous programmez dans un langage de programmation [x], il est seul responsable du compilateur [x] à créer un programme qui fait ce que vous avez décrit dans le code source . .

Si une division est demandée, le compilateur décide comment faire une division se produire. Cela pourrait arriver en générant l'opcode pour l'instruction div si la CPU que vous ciblez en a une. Il pourrait être de préciser la division au moment de la compilation et d'insérer simplement le résultat directement dans le programme (en supposant que les deux opérandes soient connus au moment de la compilation), ou cela pourrait être fait en générant une séquence d'instructions qui ensemble imiter une division.

Mais c'est toujours jusqu'au compilateur. Votre programme C ++ n'a pas aucun effet sauf s'il est interprété en fonction de la norme C ++. Si vous l'interprétez comme un fichier texte brut, il ne fait pas rien . Si votre compilateur l'interprète en tant que programme Java, il va vous étouffer et le rejeter.

Et l'instruction DIV ne sait rien sur la norme C ++. Un compilateur C ++, d'autre part, est écrit dans le seul but de comprendre la norme C ++ et de transformer le code en fonction de celui-ci.

Le compilateur est toujours responsable.


0 commentaires