Wird ein Computer versuchen, durch Null zu teilen?

59

Wir alle wissen, 0/0ist Undefinedund gibt einen Fehler zurück, wenn ich es in einen Taschenrechner stecke und wenn ich ein Programm (zumindest in C) erstelle, würde das Betriebssystem es beenden, wenn ich versuche, durch Null zu teilen.

Aber was ich mich gefragt habe, ist, ob der Computer überhaupt versucht, durch Null zu teilen , oder ob er nur "eingebauten Schutz" hat, sodass er, wenn er "sieht" 0/0, einen Fehler zurückgibt, noch bevor er versucht, ihn zu berechnen?

Ankush
quelle
10
0/0 ist undefiniert, jede andere Zahl / 0 ist eine andere Art von Fehler, Sie scheinen die beiden zu verwirren
edc65
7
Jede durch 0 geteilte Zahl ist mathematisch nicht definiert.
ManoDestra
12
@jwg: "Wenn es einen Wert hätte, wäre es 1" - nicht unbedingt; Es gibt ganze Zweige der Mathematik, die sich mit dem Wert
befassen,
11
Um zu klären , hier die Terminologie wird 0/0 eine genannte unbestimmte Form , während x / 0 für all x ist nicht definiert . Eine Berechnung, die mit 0/0 endet, kann oft anders berechnet werden, um eine echte Antwort zu erhalten, während x / 0 im Wesentlichen bedeutungslos ist.
Ära
9
@jwg Vielleicht interessiert dich dann die Regel von l'hopital. Es gibt definitiv Fälle, in denen 0/0 keinen Wert von 1 impliziert.
d0nut

Antworten:

74

Die CPU hat eine integrierte Erkennung. Die meisten Befehlssatzarchitekturen geben an, dass die CPU einen Ausnahmebehandler für die Ganzzahldivision durch Null abfängt (ich denke nicht, dass es wichtig ist, wenn die Dividende Null ist).

Es ist möglich, dass die Prüfung auf einen Nullteiler in der Hardware parallel mit dem Versuch, die Teilung durchzuführen, erfolgt. Die Erkennung des fehlerhaften Zustands löscht jedoch effektiv die Teilung und fängt stattdessen ab, sodass wir nicht wirklich sagen können, ob ein Teil vorhanden ist davon versuchte die Teilung oder nicht.

(Hardware funktioniert oft so, indem sie mehrere Dinge parallel ausführt und anschließend das entsprechende Ergebnis auswählt, da dann alle Vorgänge sofort gestartet werden können, anstatt bei der Auswahl des entsprechenden Vorgangs zu serialisieren.)

Der gleiche Trap-to-Exception-Mechanismus wird auch verwendet, wenn die Überlauferkennung aktiviert ist. Dies wird normalerweise durch die Verwendung verschiedener Add / Sub / Mul-Anweisungen (oder eines Flags in diesen Anweisungen) angefordert.

Die Gleitkommadivision hat auch die Erkennung für die Division durch Null integriert, gibt jedoch einen anderen Wert zurück ( IEEE 754 gibt NaN an ), anstatt eine Ausnahmebehandlung abzufangen.


Hypothetisch gesehen könnten die folgenden Probleme auftreten, wenn die CPU keine Erkennung für den Versuch einer Division durch Null aufweist:

  • Aufhängen der CPU (z. B. in einer inf.-Schleife) - Dies kann passieren, wenn die CPU einen Algorithmus zum Teilen verwendet, der stoppt, wenn der Zähler kleiner als der Divisor ist (in absoluten Werten). Ein Hang wie dieser würde als Absturz der CPU gelten.
  • eine (möglicherweise vorhersehbare) Müllantwort, wenn die CPU einen Zähler verwendet, um die Division mit der maximal möglichen Anzahl von Teilungsschritten zu beenden (z. B. 31 oder 32 auf einer 32-Bit-Maschine).
Erik Eidt
quelle
51
@Ankush Ein "Systemabsturz" passiert nicht wirklich auf CPU-Ebene. Das wahrscheinlichste Verhalten einer CPU, die die Division durch Null nicht abfängt, ist, dass sie einfach die Divisionsoperation ausführt, ein Unsinnergebnis erzeugt und weitermacht. Genau wie beim Hinzufügen von zwei Ganzzahlen, die zufällig überlaufen.
Ixrec
6
Für Fließkommazahlen kann die Wahl zwischen "NaN" und "Trap" normalerweise durch Umdrehen von Flags in der FPU festgelegt werden.
Vatine
10
@Ankush Für den Fall, dass das, was lxrec sagte, unklar war: Was die CPU betrifft, gibt es keinen Absturz.
user253751
7
@Ankush Wenige Situationen verursachen einen "Systemabsturz" auf CPU-Ebene. In diesen Fällen geht es um Dinge wie das Abschalten des Wärmeschutzes (Überhitzungsschutz), dreifache Fehler und ähnliche Situationen. Fast jeder Absturz, der bei normaler Verwendung auftritt , einschließlich ungültiger Opcodes , wird auf irgendeine Weise durch Abfangen und Wiederherstellen oder durch einfaches Ignorieren des Fehlers und Fortsetzen der Ausführung in einem möglicherweise unsauberen Zustand behandelt, wobei möglicherweise ein Fehlerflag gesetzt wurde.
ein Lebenslauf
8
Wenn Sie die Division durch Null nicht abgefangen hätten, wäre das Ergebnis in der Programmiersprache "Undefiniertes Verhalten". Dies bedeutet, dass der Computer alles tun kann. Es kann, wie Bergi erwähnt, in eine Buggy-Schleife eintreten und hängen bleiben. Es kann einfach eine nicht spezifizierte Reihe von Bits ausgeben, die zufällig durch die Implementierung der Teilungslogik entstanden sind (denken Sie daran, ein Computer "teilt" nicht im mathematischen Sinne. Er führt eine Operation mit zwei Zahlen durch, die der Teilung nahe genug ist dass wir es normalerweise einfach "Division" nennen .. siehe auch Gleitkomma-Rundung).
Cort Ammon
34

Dies hängt von der Sprache, dem Compiler, der Verwendung von Ganzzahlen oder Gleitkommazahlen usw. ab.

Für Gleitkommazahlen verwenden die meisten Implementierungen den IEEE 754- Standard, bei dem die Division durch 0 gut definiert ist. 0/0 ergibt ein genau definiertes Ergebnis von NaN (keine Zahl), und x / 0 für x ≠ 0 ergibt entweder + Infinity oder -Infinity, abhängig vom Vorzeichen von x.

In Sprachen wie C, C ++ usw. ruft die Division durch Null undefiniertes Verhalten auf. Entsprechend der Sprachdefinition kann also alles passieren. Vor allem Dinge, die Sie nicht passieren wollen. Wie alles, was perfekt funktioniert, wenn Sie den Code schreiben und Daten zerstören, wenn Ihr Kunde sie verwendet. Also tun Sie dies aus sprachlicher Sicht nicht . Einige Sprachen garantieren, dass Ihre Anwendung abstürzt. Es liegt an ihnen, wie dies umgesetzt wird. Bei diesen Sprachen stürzt die Division durch Null ab.

Viele Prozessoren haben eine Art eingebauten "Divide" -Befehl, der sich je nach Prozessor unterschiedlich verhält. Auf Intel 32-Bit- und 64-Bit-Prozessoren führen die "Divide" -Anweisungen zu einem Absturz Ihrer Anwendung, wenn Sie versuchen, durch Null zu dividieren. Andere Prozessoren verhalten sich möglicherweise anders.

Wenn ein Compiler feststellt, dass beim Ausführen von Code eine Division durch Null auftritt und der Compiler nett zu seinen Benutzern ist, gibt er wahrscheinlich eine Warnung aus und generiert eine eingebaute "Divide" -Anweisung, damit das Verhalten dementsprechend ist gleich.

gnasher729
quelle
22
"Auf Intel 32-Bit- und 64-Bit-Prozessoren führen die" Divide "-Anweisungen zu einem Absturz Ihrer Anwendung, wenn Sie versuchen, durch Null zu dividieren." Zitat benötigt. CPUs haben keine Ahnung von Anwendungen, sie führen Anweisungen aus und erzwingen (sofern wir die MMU einbeziehen) Speicherzugriffsbeschränkungen (sofern nicht in Ring 0 oder einer Entsprechung in Nicht-Intel-x86-Architekturen). Dass der Befehl Teil der Anwendung A und nicht der Anwendung B oder der Betriebssystemkomponente C ist, ist für die CPU irrelevant. es ist relevant, ob der Befehl Befehl X sein kann oder Speicheradresse Y verwendet.
ein Lebenslauf
1
Hinzufügen zu @ MichaelKjörling Kommentar: Das Betriebssystem hat Möglichkeiten, die Anwendung dieses (und anderer Arten von Fehlern) zu überprüfen. In der Windows-Welt ist dies der EXCEPTION_INT_DIVIDE_BY_ZEROWert, der EXCEPTION_RECORDvom (hoffentlich) installierten Structed Exception Handling Handler
user45891
1
Manchmal tun sie etwas anderes als zu garantieren, dass Ihre App abstürzt. Beispielsweise garantieren viele Sprachen / Plattformen, dass sie eine Ausnahme bei der Division durch Null auslösen. Sie können diese Ausnahme dann abfangen und behandeln, ohne abstürzen zu müssen.
Reirab
2
Sie können das "may" unter "Andere Prozessoren verhalten sich möglicherweise anders" löschen: Auf der PowerPC-Plattform erzeugt die Division nur ein Nullergebnis bei Division durch Null. Das ist viel nützlicher als das Panikverhalten der X86-Plattform.
cmaster
13

Scheint, als würden Sie sich fragen, was passieren würde, wenn jemand eine CPU baut, die vor dem Teilen nicht explizit auf Null prüft. Was passieren würde, hängt ganz von der Implementierung der Division ab. Ohne auf Details einzugehen, würde eine Art von Implementierung ein Ergebnis erzeugen, bei dem alle Bits gesetzt sind, z. B. 65535 auf einer 16-Bit-CPU. Ein anderer könnte auflegen.

Bingo
quelle
1

Aber was ich mich gefragt habe, ist, ob der Computer überhaupt versucht, durch Null zu teilen, oder ob er nur "eingebauten Schutz" hat, so dass er, wenn er "0/0" sieht, einen Fehler zurückgibt, noch bevor er versucht, ihn zu berechnen?

Da x/0der Punkt keinen Sinn ergibt, müssen Computer immer auf Division durch Null prüfen. Hier gibt es ein Problem: Programmierer wollen rechnen, (a+b)/cohne prüfen zu müssen, ob diese Berechnung überhaupt Sinn macht. Die Reaktion unter der Haube auf die Division durch Null durch CPU + Zahlentyp + Betriebssystem + Sprache besteht darin, entweder etwas ziemlich drastisches zu tun (z. B. das Programm zum Absturz zu bringen) oder etwas übermäßig Gutes zu tun (z. B. einen Wert zu erstellen, der Nein ergibt Sinn wie der IEEE-Gleitkommawert NaN, eine Zahl, die "keine Zahl" ist).

In einer gewöhnlichen Umgebung muss ein Programmierer wissen, ob dies (a+b)/csinnvoll ist. In diesem Zusammenhang gibt es keinen Grund, die Division durch Null zu überprüfen. Wenn eine Division durch Null auftritt und die Maschinensprache + die Implementierungssprache + der Datentyp + das Betriebssystem darauf reagieren, um das Programm zum Absturz zu bringen, ist das in Ordnung. Wenn die Antwort darin besteht, einen Wert zu erstellen, der eventuell jede Zahl im Programm verschmutzt, ist das auch in Ordnung.

Weder "etwas Drastisches" noch "übermäßig Gutes" ist in der Welt des Hochzuverlässigkeits-Computing das Richtige. Diese Standardantworten können einen Patienten töten, ein Verkehrsflugzeug zum Absturz bringen oder eine Bombe am falschen Ort explodieren lassen. In einer hochzuverlässigen Umgebung wird ein Programmierer, der schreibt (a+b)/c, während der Codeüberprüfung oder in der heutigen Zeit von einem Tool, das nach verbotenen Konstrukten sucht, automatisch zu Tode gerissen. In dieser Umgebung sollte der Programmierer stattdessen etwas in der Art geschrieben haben div(add(a,b),c)(und möglicherweise nach dem Fehlerstatus suchen). Unter der Haube schützen die div(und auch die add) Funktionen / Makros vor einer Division durch Null (oder einem Überlauf bei add). Was dieser Schutz beinhaltet, ist sehr umsetzungsspezifisch.

David Hammen
quelle
Nur weil NaN der in der Schule gelernten Arithmetik nicht gehorcht, macht das noch lange keinen Sinn. Es gehorcht anderen Arithmetik
Caleth
-2

Das wissen wir inzwischen x/0und 0/0haben keine genau definierten Antworten. Was passiert, wenn Sie 0/0trotzdem versuchen zu berechnen ?

Auf einem modernen System wird die Berechnung an die MPU in der CPU übergeben und als unzulässige Operation gekennzeichnet, die zurückkehrt NaN.

Auf einem viel älteren System, wie z. B. Heimcomputern der 80er Jahre, die keine On-Chip-Unterteilung hatten, wurde die Berechnung von jeder Software durchgeführt, die ausgeführt wurde. Es gibt einige Möglichkeiten:

  • Subtrahieren Sie immer kleinere Kopien des Divisors, bis der Wert Null erreicht, und verfolgen Sie, welche Kopiengrößen subtrahiert wurden
    • Wenn es vor der ersten Subtraktion nach Null sucht, wird es schnell beendet und das Ergebnis ist 0
    • Wenn es annimmt, dass es in der Lage sein muss, mindestens einmal zu subtrahieren, wird das Ergebnis sein 1
  • Berechnen Sie die Logarithmen beider Zahlen, subtrahieren Sie sie und erhöhen Sie e zur Potenz des Ergebnisses. Eine sehr ineffiziente Methode im Vergleich zur obigen Subtraktionsmethode, aber mathematisch gültig
    • Beim Berechnen kann ein Überlauf auftreten, log(0)und die Software verwendet entweder ihre Fehlerbehandlungsroutinen oder stürzt ab
    • Die Software geht möglicherweise davon aus, dass alle Logarithmen in einer festen Anzahl von Schritten berechnet werden können und einen großen, aber falschen Wert zurückgeben. Da beide Logarithmen gleich wären, wäre die Differenz 0und e 0 = 1, was ein Ergebnis von ergibt1

Mit anderen Worten, es wäre implementierungsabhängig, was passieren würde, und es wäre möglich, Software zu schreiben, die für jeden Wert korrekte und vorhersehbare Ergebnisse liefert, für 0/0die es jedoch seltsame Werte gibt, die dennoch intern konsistent sind.

CJ Dennis
quelle
3
Bei dieser Frage geht es um die Division durch Null in ganzen Zahlen, und es gibt keine NaNGanzzahlen.
David Hammen
3
Keine CPU wird Protokolle berechnen und subtrahieren, um das Ergebnis der Division zu berechnen. Das Timing des Logarithmusbefehls ist mehrere Größenordnungen größer als eine Division. Was ist der Wert von log (0)?
Wallyk
1
@DavidHammen Das OP erwähnte niemals ganze Zahlen, und auch niemand, der sich zu dieser Frage äußerte. Ganzzahlen werden nur in Antworten erwähnt.
CJ Dennis
@wallyk Ich sagte bereits in meiner Antwort, dass diese Logarithmen very inefficientfür die Division sind. Die Kosten für die Arithmetik betragen (Addition = Subtraktion) <= Multiplikation <= Division. Wenn Sie keine MPU haben, die Division in der gleichen Anzahl von Taktzyklen wie Addition (normalerweise eine) ausführen kann, ist Division teurer als Addition und Subtraktion und normalerweise auch teurer als Multiplikation.
CJ Dennis