2010-08-15 12 views
7

Ho programmato per un po 'in C++, ma all'improvviso ho avuto un dubbio e volevo chiarire con la community Stackoverflow.Integer vs floating division -> Chi è responsabile della fornitura del risultato?

Quando un numero intero è diviso per un altro numero intero, sappiamo tutti il ​​risultato è un numero intero e come saggio, un galleggiante divisa dal galleggiante è anche un galleggiante.

Ma chi è responsabile della fornitura di questo risultato? È il compilatore o l'istruzione DIV?

+1

State divideva il costanti o variabili? –

risposta

3

Il compilatore deciderà al momento della compilazione quale forma di divisione sia richiesta in base ai tipi di variabili utilizzate; alla fine del giorno verrà coinvolta un'istruzione DIV (o FDIV) di una forma o di un'altra.

+1

A meno che le variabili non siano costanti in fase di compilazione, nel qual caso il compilatore si "assumerà la responsabilità" e non verranno fornite istruzioni. – Potatoswatter

+0

@Potatoswatter: non completamente vero; il compilatore DEVE valutare le espressioni costanti integrali e MAGGIO valutare altre espressioni costanti. Cioè 'float x = 1.0/3.0' può essere valutato dal compilatore, o può risultare in una scelta del compilatore FDIV. – MSalters

11

Questo dipende o meno dall'architettura a DIV. Se la tua architettura ha sia istruzioni intere che divise a virgola mobile, il compilatore emetterà le istruzioni corrette per il caso specificato dal codice. Lo standard della lingua specifica le regole per la promozione del tipo e se la divisione in intero o in virgola mobile deve essere utilizzata in ogni possibile situazione.

Se si dispone di un'istruzione di divisione intera o solo di un'istruzione di divisione a virgola mobile, il compilatore inline un codice o genera una chiamata a una libreria di supporto matematico per gestire la divisione. Le istruzioni di divisione sono notoriamente lente, quindi la maggior parte dei compilatori tenterà di ottimizzarle, se possibile (ad es. Sostituire le istruzioni di spostamento o precalcolare il risultato per una divisione di costanti in fase di compilazione).

3

Le istruzioni di divisione dell'hardware non includono quasi mai la conversione tra numero intero e virgola mobile. Se si ottengono istruzioni di divisione (a volte vengono omesse, poiché un circuito di divisione è ampio e complicato), sono praticamente certi di essere "divide int da int, produrre int" e "divide float per float, produce float" . In genere, sia gli input che l'output hanno le stesse dimensioni.

Il compilatore è responsabile per la costruzione di qualunque operazione è stato scritto nel codice sorgente, in cima a questi primitivi. Ad esempio, in C, se dividi un float con un int, il compilatore emetterà una conversione int-to-float e quindi una divisione float.

(Le eccezioni di Wacky esistono, non lo so, ma non lo metterei oltre il VAX per avere istruzioni di tipo "divide float by int". L'Itanium non ha realmente un'istruzione di divisione, ma sua "divide helper" era solo per virgola mobile, si doveva falso divisione intera in cima galleggiante divide!)

+0

Heh. Per quanto riguarda le "stravaganti eccezioni", come le chiami, probabilmente ne hai usato uno proprio ora per scrivere questa risposta. L'istruzione x86 (o più precisamente x87) per * divide float di int * si chiama FIDIV. – slacker

+1

E non è l'unico punto in cui la stranezza di x86 mette il vergogna VAX :). – slacker

+0

Hah! Bene, sarebbe l'x87. Non hanno fatto _qualcosa_ nel modo normale con quella cosa. – zwol

0

Praticamente

lo standard C99 definisce "Quando interi vengono divisi, il risultato della/l'operatore è il quoziente algebrico con qualsiasi parte frazionaria scartata. " E aggiunge in una nota che "questo è spesso chiamato 'il troncamento verso lo zero'".

Storia

Storicamente, la specifica del linguaggio è responsabile.

Pascal defines its operators in modo che l'utilizzo di / per la divisione restituisce sempre un real (anche se lo si utilizza per dividere 2 numeri interi), e se si vuole dividere interi e ottenere un risultato intero, si utilizza l'operatore div invece. (Visual Basic ha una distinzione simile e utilizza l'operatore \ per la divisione integer che restituisce un risultato intero.)

In C, è stato deciso che la stessa distinzione dovrebbe essere eseguita mediante il cast di uno degli operandi interi su un float se si desidera un risultato in virgola mobile. È diventato convenzione trattare i tipi interi e in virgola mobile come descritto in molti linguaggi derivati ​​da C. Sospetto che questa convenzione possa aver avuto origine in Fortran.

1

Una delle regole più importanti nello standard C++ è il "come se" regola:

Le descrizioni semantiche nella presente norma internazionale definisce un parametrizzato non deterministico macchina astratta. Questo standard internazionale non impone alcun requisito sulla struttura delle implementazioni conformi. In particolare, non è necessario copiare o emulare la struttura della macchina astratta. Piuttosto, sono necessarie implementazioni conformi per emulare (solo) il comportamento osservabile della macchina astratta come spiegato di seguito.

Che in relazione alla tua domanda significa che non importa quale componente fa la divisione, a patto che venga eseguita. Può essere eseguito da un codice macchina DIV, può essere eseguito da un codice più complicato se non c'è un'istruzione appropriata per il processore in questione.

E 'possibile anche:

  1. Sostituire l'operazione con un'operazione di po-shift, se del caso e in grado di essere più veloce.
  2. Sostituire l'operazione con un valore letterale se computabile in fase di compilazione o un'assegnazione se ad es. durante l'elaborazione di x/y può essere mostrato in fase di compilazione che y sarà sempre 1.
  3. Sostituisci l'operazione con un lancio di eccezione se può essere mostrato in fase di compilazione che sarà sempre una divisione intera per zero.
+0

Potrebbe rifiutano compilare se potrebbe dedurre al momento della compilazione che il quoziente sarebbe sempre zero, o è legittimo per un programma completamente conforme C per contenere un'istruzione come x = 1/(x-x); fornito che tale istruzione non venga mai eseguita? – supercat

+0

@supercat: È perfettamente legittimo. È l'* esecuzione * di una divisione per zero che causa un comportamento indefinito. – slacker

+1

@supercat se vuoi produrre un programma che fa sempre errori, è affar tuo! Dopotutto è difficile insegnare alle persone errori senza di loro (anche se in alcune lingue devi fare cose come "if (true == false)" per ingannare i compilatori facendoti compilare). Sarebbe certamente ragionevole, e utile, che il compilatore producesse un avvertimento non standardizzato. –

1

La tua domanda non ha molto senso. L'istruzione DIV non esegue nulla da solo. Non importa quanto tu gridi, anche se provi a corromperlo, non si assume alcuna responsabilità per nulla

Quando si programma in un linguaggio di programmazione [X], è la sola responsabilità del [ X] al compila un programma che fa ciò che hai descritto nel codice sorgente.

Se viene richiesta una divisione, il compilatore decide come effettuare una divisione. Ciò potrebbe accadere generando l'opcode per l'istruzione DIV, se la CPU che hai scelto come target ne ha uno. Potrebbe essere precalcolando la divisione in fase di compilazione e semplicemente inserendo il risultato direttamente nel programma (presupponendo che entrambi gli operandi siano noti in fase di compilazione), oppure potrebbe essere fatto generando una sequenza di istruzioni che insieme emulano a Divison.

Ma è sempre fino al compilatore. Il tuo programma C++ non ha alcun effetto a meno che non sia interpretato secondo lo standard C++. Se lo interpreti come un semplice file di testo, non lo fa nulla. Se il compilatore lo interpreta come un programma Java, lo strozzerà e lo rifiuterà.

E l'istruzione DIV non conosce nulla sullo standard C++.Un compilatore C++, d'altra parte, è scritto con il solo scopo di comprendere standard C++, e trasformando codice secondo essa.

Il compilatore è sempre responsabile.

Problemi correlati