Un computer tenterà di dividere per zero?


59

Sappiamo tutti che 0/0è Undefinede restituisce un errore se dovessi inserirlo in una calcolatrice e se dovessi creare un programma (almeno in C) il sistema operativo lo terminerebbe quando provo a dividere per zero.

Ma quello che mi chiedevo è se il computer tenta persino di dividere per zero , o ha solo "protezione integrata", in modo che quando "vede" 0/0restituisce un errore anche prima di tentare di calcolarlo?


10
0/0 non è definito, qualsiasi altro numero / 0 è un diverso tipo di errore, sembri confondere i due
edc65,

7
Qualsiasi numero diviso per 0 è indefinito, matematicamente parlando.
ManoDestra,

12
@jwg: "se avesse un valore sarebbe 1" - non necessariamente; ci sono interi rami della matematica dedicati a quale potrebbe essere il valore in diverse circostanze :)
psmears,

11
Per chiarire qui la terminologia, 0/0 è chiamato una forma indeterminata mentre x / 0 per nonzero x non è definito . Un calcolo che termina con 0/0 può spesso essere calcolato in modo diverso per dare una risposta reale, mentre x / 0 è essenzialmente insignificante.
Era il

9
@jwg allora potresti essere interessato alla regola dell'hopital. Ci sono sicuramente casi in cui 0/0 non implica un valore di 1.
d0nut,

Risposte:


74

La CPU ha un rilevamento integrato. La maggior parte delle architetture del set di istruzioni specifica che la CPU eseguirà il trap a un gestore di eccezioni per la divisione di numeri interi per zero (non credo che importi se il dividendo è zero).

È possibile che il controllo per un divisore zero avvenga in parallelo nell'hardware insieme al tentativo di fare la divisione, tuttavia, il rilevamento della condizione offensiva annulla effettivamente la divisione e le trappole, quindi non possiamo davvero dire se una parte ne tentò la divisione o no.

(L'hardware spesso funziona in questo modo, facendo più cose in parallelo e quindi scegliendo il risultato appropriato in seguito perché in seguito ciascuna delle operazioni può iniziare immediatamente invece di serializzare sulla scelta dell'operazione appropriata.)

Lo stesso meccanismo trap to exception verrà utilizzato anche quando viene attivato il rilevamento di overflow, che di solito si richiede utilizzando diverse istruzioni add / sub / mul (o un flag su tali istruzioni).

Anche la divisione in virgola mobile ha un rilevamento incorporato per la divisione per zero, ma restituisce un valore diverso ( IEEE 754 specifica NaN ) invece di eseguire il trapping a un gestore eccezioni.


Ipoteticamente parlando, se la CPU omettesse qualsiasi rilevamento per tentare di dividere per zero, i problemi potrebbero includere:

  • sospensione della CPU (ad es. in un loop inf.): ciò potrebbe accadere se la CPU utilizza un algoritmo per dividere che si arresta quando il numeratore è inferiore al divisore (in valore assoluto). Un blocco come questo conta praticamente come crash della CPU.
  • una risposta di immondizia (probabilmente prevedibile), se la CPU utilizza un contatore per terminare la divisione al numero massimo possibile di passaggi di divisione (ad es. 31 o 32 su una macchina a 32 bit).

51
@Ankush Un "crash di sistema" non è realmente qualcosa che accade a livello di CPU. Il comportamento più probabile di una CPU che non ha intercettato il divario per zero sarebbe che esegue semplicemente l'operazione di divisione, produce alcuni risultati senza senso e continua. Proprio come quando aggiungi due numeri interi che si verificano traboccando.
Ixrec,

6
Per il virgola mobile, la scelta tra "NaN" e "trap" è di solito impostabile lanciando flag nella FPU.
Vatine,

10
@Ankush Nel caso ciò che dicesse lxrec non fosse chiaro: per quanto riguarda la CPU, non esiste un crash.
user253751,

7
@Ankush Poche situazioni causano un "crash di sistema" a livello di CPU. In questi casi stiamo parlando di cose come l'arresto della protezione termica (protezione da surriscaldamento), i guasti tripli e situazioni simili. Quasi tutti gli arresti anomali che si incontrano nell'uso ordinario, compresi i codici operativi non validi , vengono gestiti tramite il trapping e il ripristino in qualche modo, o semplicemente ignorando l'errore e continuando l'esecuzione in uno stato potenzialmente impuro, magari avendo impostato un flag di errore.
un CVn il

8
Se non hai intrappolato la divisione per zero, il risultato sarebbe, nel linguaggio di programmazione, "Comportamento indefinito". Ciò significa che il computer può fare qualsiasi cosa. Potrebbe, come menziona Bergi, entrare in un circuito con buggy e bloccarsi. Può semplicemente produrre alcune serie di bit non specificate che sono risultate essere ciò che è venuto dalla loro implementazione della logica di divisione (ricordate, un computer non "divide" in senso matematico. Fa un'operazione su due numeri, che è abbastanza vicino alla divisione che di solito chiamiamo semplicemente "divisione" .. vedi anche arrotondamento in virgola mobile).
Cort Ammon,

34

Dipende dalla lingua, dal compilatore, dal fatto che si utilizzino numeri interi o numeri in virgola mobile e così via.

Per il numero in virgola mobile, la maggior parte delle implementazioni utilizza lo standard IEEE 754 , dove la divisione per 0 è ben definita. 0/0 fornisce un risultato ben definito di NaN (non un numero) e x / 0 per x ≠ 0 indica + Infinito o -Infinito, a seconda del segno di x.

In linguaggi come C, C ++ ecc. La divisione per zero invoca un comportamento indefinito. Quindi, secondo la definizione della lingua, tutto può succedere. Soprattutto cose che non vuoi che accadano. Come tutto funziona perfettamente quando si scrive il codice e si distruggono i dati quando il cliente lo utilizza. Quindi dal punto di vista linguistico, non farlo . Alcune lingue garantiscono il crash dell'applicazione; dipende da loro come questo è implementato. Per quelle lingue, la divisione per zero andrà in crash.

Molti processori hanno una sorta di istruzione "divide" integrata, che si comporterà in modo diverso a seconda del processore. Sui processori Intel a 32 bit e 64 bit, le istruzioni "divide" causeranno il crash dell'applicazione quando si tenta di dividere per zero. Altri processori potrebbero comportarsi diversamente.

Se un compilatore rileva che si verificherà una divisione per zero quando si esegue del codice e il compilatore è utile per i suoi utenti, probabilmente ti darà un avvertimento e genererà un'istruzione di "divisione" incorporata in modo che il comportamento sia il stesso.


22
"Su processori Intel a 32 bit e 64 bit, le istruzioni" divide "causeranno il crash dell'applicazione quando si tenta di dividere per zero." Citazione necessaria. Le CPU non hanno idea delle applicazioni, eseguono le istruzioni e (se includiamo la MMU) applicano limiti di accesso alla memoria (a meno che non siano nell'anello 0 o equivalenti in architetture non Intel-x86). Che l'istruzione faccia parte dell'applicazione A anziché dell'applicazione B o del componente C del sistema operativo è irrilevante per la CPU; se l'istruzione può essere Istruzione X o utilizzare l'indirizzo di memoria Y è rilevante.
un CVn il

1
Per aggiungere al commento @ MichaelKjörling: il sistema operativo ha modi di notificare l'applicazione di questo (e altri tipi di errori). Nel mondo di Windows è il EXCEPTION_INT_DIVIDE_BY_ZEROvalore in EXCEPTION_RECORDcui verrà gestito dal (si spera) gestore di gestione delle eccezioni strutturata (si spera) installato
user45891

1
A volte fanno altre cose oltre a garantire che l'app si arresti in modo anomalo. Ad esempio, molte lingue / piattaforme garantiscono che genereranno un'eccezione sulla divisione per zero. È quindi possibile catturare e gestire detta eccezione senza arresti anomali.
reirab

2
È possibile eliminare "may" in "Altri processori potrebbero comportarsi diversamente": Sulla piattaforma PowerPC, la divisione produce solo un risultato zero sulla divisione per zero. Che è molto più utile del comportamento di panico della piattaforma X86.
cmaster

13

Sembra che ti stia chiedendo cosa succederebbe se qualcuno creasse una CPU che non controlla esplicitamente lo zero prima della divisione. Cosa succederebbe dipende interamente dall'attuazione della divisione. Senza entrare nei dettagli, un tipo di implementazione produrrebbe un risultato con tutti i bit impostati, ad esempio 65535 su una CPU a 16 bit. Un altro potrebbe riattaccare.


1

Ma quello che mi chiedevo è se il computer tenta persino di dividere per zero, o ha solo "protezione integrata", in modo che quando "vede" 0/0 restituisce un errore anche prima di tentare di calcolarlo?

Dal momento x/0che non ha senso, punto, i computer devono sempre controllare la divisione per zero. C'è un problema qui: i programmatori vogliono calcolare (a+b)/csenza doversi preoccupare di verificare se quel calcolo ha persino senso. La risposta nascosta alla divisione per zero per CPU + tipo di numero + sistema operativo + linguaggio è quella di fare qualcosa di piuttosto drastico (ad esempio, bloccare il programma) o fare qualcosa di eccessivamente benigno (ad esempio, creare un valore che non fa senso come il virgola mobile IEEE NaN, un numero che è "Not a Number").

In un ambiente normale, un programmatore dovrebbe sapere se (a+b)/cha senso. In questo contesto, non c'è motivo di verificare la divisione per zero. Se si verifica una divisione per zero e se il linguaggio macchina + linguaggio di implementazione + tipo di dati + risposta del sistema operativo a questo è quello di causare l'arresto anomalo del programma, va bene. Se la risposta è creare un valore che potrebbe eventualmente inquinare ogni numero nel programma, va bene lo stesso.

Né "qualcosa di drastico" o "eccessivamente benigno" è la cosa giusta da fare nel mondo dell'informatica ad alta affidabilità. Quelle risposte predefinite potrebbero uccidere un paziente, far schiantare un aereo di linea o far esplodere una bomba nel posto sbagliato. In un ambiente ad alta affidabilità, un programmatore che scrive (a+b)/cverrà scelto a morte durante la revisione del codice, o nei tempi moderni, forse scelto automaticamente a morte da uno strumento che verifica la presenza di costrutti verboten. In questo ambiente, quel programmatore dovrebbe invece aver scritto qualcosa sulla falsariga di div(add(a,b),c)(e forse un po 'di controllo dello stato di errore). Sotto il cofano, le funzioni div(e anche le add) / macro proteggono dalla divisione per zero (o overflow nel caso di add). Ciò che tale protezione comporta è molto specifico per l'implementazione.


Solo perché NaN non obbedisce all'aritmetica che hai imparato a scuola non significa che non abbia senso. Obbedisce a diverse aritmetiche
Caleth,

-2

Ormai lo sappiamo x/0e 0/0non abbiamo risposte ben definite. Cosa succede se si tenta di calcolare 0/0comunque?

Su un sistema moderno, il calcolo viene passato alla MPU all'interno della CPU e viene contrassegnato come un'operazione illegale, di ritorno NaN.

Su un sistema molto più vecchio, come i computer domestici degli anni '80 che non avevano una divisione su chip, il calcolo veniva eseguito da qualunque software fosse in esecuzione. Vi sono alcune scelte possibili:

  • Sottrai le copie sempre più piccole del divisore fino a quando il valore non raggiunge lo zero e tieni traccia delle copie sottratte
    • Se verifica lo zero prima della prima sottrazione, uscirà rapidamente e il risultato sarà 0
    • Se assume che debba essere in grado di sottrarre almeno una volta, il risultato sarà 1
  • Calcola i logaritmi di entrambi i numeri, sottrali e aumenta e alla potenza del risultato. Un metodo molto inefficiente rispetto al precedente metodo di sottrazione, ma matematicamente valido
    • Potrebbe verificarsi un overflow nel tentativo di calcolare log(0)e il software userebbe la sua routine di gestione degli errori o si arresterebbe in modo anomalo
    • Il software potrebbe presumere che tutti i logaritmi possano essere calcolati in un numero fisso di passaggi e restituire un valore elevato, ma non corretto. Poiché entrambi i logaritmi sarebbero uguali, la differenza sarebbe 0e e 0 = 1, dando un risultato di1

In altre parole, ciò dipenderebbe dall'implementazione e sarebbe possibile scrivere un software che produca risultati corretti e prevedibili per ogni valore, ma valori apparentemente strani per 0/0quello sono comunque coerenti internamente.


3
Questa domanda riguarda la divisione per zero negli interi e non esiste nulla come NaNnegli interi.
David Hammen,

3
Nessuna CPU calcolerà i log e sottrarrà per calcolare il risultato della divisione. Il tempismo delle istruzioni del logaritmo è di diversi ordini di grandezza maggiori di una divisione. Qual è il valore di log (0)?
Wallyk,

1
@DavidHammen L'OP non ha mai menzionato numeri interi e nessuno ha commentato la domanda. I numeri interi sono indicati solo nelle risposte.
CJ Dennis,

@wallyk Ho già detto nella mia risposta che i logaritmi sono very inefficientper la divisione. Il costo per l'aritmetica è (addizione = sottrazione) <= moltiplicazione <= divisione. Se non si dispone di una MPU in grado di eseguire la divisione nello stesso numero di cicli di clock dell'addizione (di solito una), la divisione è più costosa dell'addizione e della sottrazione e di solito più costosa anche della moltiplicazione.
CJ Dennis,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.