web-dev-qa-db-fra.com

Un ordinateur tentera-t-il de diviser par zéro?

Nous savons tous 0/0 est Undefined et renvoie une erreur si je le mettais dans une calculatrice, et si je devais créer un programme (en C au moins), le système d'exploitation le terminerait lorsque j'essaierais de diviser par zéro.

Mais ce que je me demandais, c'est si l'ordinateur tente même de diviser par zéro, ou a-t-il simplement une "protection intégrée", de sorte que lorsqu'il "voit" 0/0 il renvoie une erreur avant même de tenter de le calculer?

59
Ankush

Le CPU a intégré la détection. La plupart des architectures de jeux d'instructions spécifient que le CPU va intercepter un gestionnaire d'exceptions pour la division entière par zéro (je ne pense pas que cela se soucie si le dividende est nul).

Il est possible que la vérification d'un diviseur nul se déroule en parallèle dans le matériel avec la tentative de division, cependant, la détection de la condition incriminée annule effectivement la division et les pièges à la place, donc nous ne pouvons pas vraiment dire si une partie de celui-ci a tenté la division ou non.

(Le matériel fonctionne souvent comme ça, en faisant plusieurs choses en parallèle, puis en choisissant ensuite le résultat approprié, car chacune des opérations peut commencer immédiatement au lieu de sérialiser sur le choix de l'opération appropriée.)

Le même mécanisme de déroutement à exception sera également utilisé lorsque la détection de débordement est activée, ce que vous demandez généralement en utilisant différentes instructions add/sub/mul (ou un indicateur sur ces instructions).

La division en virgule flottante a également intégré la détection de la division par zéro, mais renvoie une valeur différente ( IEEE 754 spécifie NaN ) au lieu de piéger vers un gestionnaire d'exceptions.


En théorie, si le processeur a omis toute détection pour tenter de diviser par zéro, les problèmes pourraient inclure:

  • accrocher le CPU (par exemple dans une boucle inf.) - cela peut arriver si le CPU utilise un algorithme de division qui s'arrête lorsque le numérateur est inférieur au diviseur (en valeur absolue). Un blocage comme celui-ci compterait à peu près comme un crash du processeur.
  • une réponse poubelle (éventuellement prévisible), si le CPU utilise un compteur pour terminer la division au nombre maximum possible d'étapes de division (par exemple 31 ou 32 sur une machine 32 bits).
74
Erik Eidt

Cela dépend de la langue, du compilateur, de l'utilisation de nombres entiers ou à virgule flottante, etc.

Pour le nombre à virgule flottante, la plupart des implémentations utilisent la norme IEEE 754 , où la division par 0 est bien définie. 0/0 donne un résultat bien défini de NaN (pas un nombre), et x/0 pour x ≠ 0 donne + Infinity ou -Infinity, selon le signe de x.

Dans des langages comme C, C++, etc., la division par zéro invoque un comportement indéfini. Donc, selon la définition du langage, tout peut arriver. Surtout des choses que vous ne voulez pas voir se produire. Comme tout fonctionne parfaitement bien lorsque vous écrivez le code et détruit les données lorsque votre client l'utilise. Donc, du point de vue de la langue, ne faites pas cela . Certaines langues garantissent que votre application plantera; c'est à eux comment cela est mis en œuvre. Pour ces langues, la division par zéro se bloquera.

De nombreux processeurs ont une sorte d'instruction de "division" intégrée, qui se comportera différemment selon le processeur. Sur les processeurs Intel 32 bits et 64 bits, les instructions "diviser" plantent votre application lorsque vous essayez de diviser par zéro. D'autres processeurs peuvent se comporter différemment.

Si un compilateur détecte qu'une division par zéro se produira lorsque vous exécuterez du code et que le compilateur est agréable pour ses utilisateurs, il vous donnera probablement un avertissement et générera une instruction de "division" intégrée afin que le comportement soit le même.

34
gnasher729

On dirait que vous vous demandez ce qui se passerait si quelqu'un faisait un CPU qui ne vérifie pas explicitement zéro avant de diviser. Ce qui se passerait dépend entièrement de la mise en œuvre de la division. Sans entrer dans les détails, un type d'implémentation produirait un résultat avec tous les bits définis, par ex. 65535 sur un processeur 16 bits. Un autre pourrait raccrocher.

13
Bingo

Mais ce que je me demandais, c'est si l'ordinateur tente même de diviser par zéro, ou a-t-il simplement une "protection intégrée", de sorte que lorsqu'il "voit" 0/0, il renvoie une erreur avant même de tenter de le calculer?

Puisque x/0 N'a aucun sens, point, les ordinateurs doivent toujours vérifier la division par zéro. Il y a un problème ici: les programmeurs veulent calculer (a+b)/c Sans avoir à se soucier de vérifier si ce calcul est logique. La réponse sous-jacente à la division par zéro par le CPU + le type de numéro + le système d'exploitation + la langue est soit de faire quelque chose de plutôt radical (par exemple, planter le programme) ou de faire quelque chose de trop bénin (par exemple, créer une valeur qui ne fait pas sens tel que le point flottant IEEE NaN, un nombre qui est "Pas un nombre").

Dans un cadre ordinaire, un programmeur doit savoir si (a+b)/c Est logique. Dans ce contexte, il n'y a aucune raison de vérifier la division par zéro. Si la division par zéro se produit, et si la réponse du langage machine + langage d'implémentation + type de données + système d'exploitation est de faire planter le programme, c'est correct. Si la réponse est de créer une valeur qui pourrait éventuellement polluer chaque numéro du programme, c'est bien aussi.

Ni "quelque chose de radical" ni de "trop bénin" n'est la bonne chose à faire dans le monde de l'informatique à haute fiabilité. Ces réponses par défaut peuvent tuer un patient, écraser un avion de ligne ou faire exploser une bombe au mauvais endroit. Dans un environnement à haute fiabilité, un programmeur qui écrit (a+b)/c Sera tué à mort lors de la révision du code, ou dans les temps modernes, peut-être automatiquement à mort par un outil qui vérifie les constructions verboten. Dans cet environnement, ce programmeur aurait plutôt dû écrire quelque chose dans le sens de div(add(a,b),c) (et peut-être un peu vérifier l'état d'erreur). Sous le capot, les fonctions/macros div (et aussi add) protègent contre la division par zéro (ou le débordement dans le cas de add). Ce que cette protection implique est très spécifique à la mise en œuvre.

1
David Hammen