2014-12-24 13 views
6

Recentemente ho provato il seguente programma & mi aspettavo errore di runtime ma mostra "nan" come output. Perché & Come? Sto usando il compilatore g ++.perché 0.0f/0.0f non genera alcun errore di runtime?

#include <iostream> 
int main() 
{ 
    float f=0.0f/0.0f; 
    std::cout<<f; 
    return 0; 
} 

stesso modo ho anche cercato simile tipo di programma in Java & C# & si dimostra ancora una volta "nan" come output.

class Test 
{ 
    public static void main(String args[]) 
    { 
     float f=0.0f/0.0f; 
     System.out.println(f); 
    } 
} 

class Test 
{ 
    public static void Main(string[] args) 
    { 
     float f=0.0f/0.0f; 
     Console.Write(f); 
    } 
} 

Voglio sapere che come aritmetica in virgola mobile è implementato & come differes da aritmetica intera. È un comportamento indefinito nel caso del C++? Se sì, perché? Per favore aiutatemi.

+2

Perché è quello che dice la specifica in virgola mobile. https://en.wikipedia.org/wiki/IEEE_floating_point – SLaks

+0

Un altro link: http://support.microsoft.com/kb/42980. –

risposta

9

nan significa non un numero. Dividere per l'intero 0 è sempre un errore, perché non puoi dividere per 0 in matematica. Pertanto molte lingue generano un'eccezione quando si divide per il numero intero 0.

Sarebbe meno ragionevole farlo con numeri in virgola mobile perché i calcoli in virgola mobile non sono esatti. Ad esempio, un calcolo potrebbe risultare in 0.0f perché 0.0f è il valore in virgola mobile più vicino alla risposta, non perché il valore vero della risposta è matematicamente 0. Pertanto, provare a dividere per il valore in virgola mobile 0.0f potrebbe non essere una conseguenza di un algoritmo errato. In sostanza significa che la risposta al calcolo non può essere determinata perché implicava la divisione di due numeri talmente piccoli che era impossibile per il computer distinguerli da 0.

+1

Nota anche alcune lingue restituiscono PositiveInfinity (o l'equivalente) poiché alcune forme di matematica lo rendono corretto: http://msdn.microsoft.com/en-us/library/system.double.positiveinfinity%28v=vs.110%29. aspx – David

+0

@Aravol Grazie per questo. Ho cambiato l'ultima frase in "la divisione di DUE numeri ..." perché, come dici correttamente, la divisione per 0.0f può portare a valori diversi da nan, a seconda del valore del numeratore. –

2

Da http://en.wikipedia.org/wiki/NaN#Operations_generating_NaN:

operazioni che generano NaN

ci sono tre tipi di operazioni che possono restituire NaN:

  • operazioni con un NaN come almeno un operando.
  • Forme indeterminate
    • Le divisioni 0/0 e ± ∞/± ∞
    • Le moltiplicazioni 0 × ± ∞ e ± ∞ × 0
    • Le aggiunte ∞ + (-∞), (-∞) + ∞ e sottrazioni equivalenti

... ecc

+0

quelli che in realtà sono matematici e chiamati indeterminati, possono essere trovati trovando i limiti di una funzione – niceman

+0

@ user2397162, l'articolo che ho collegato ai discorsi su IEEE 754, il documento che è uno standard tecnico per rappresentare numeri in virgola mobile e operazioni su di essi . –

+0

e la matematica è d'accordo con loro, se non si è sicuri di leggere i limiti di ricerca di una funzione – niceman

2

È perché, di default, il C++ esegue le librerie temporali mascherano tutte le eccezioni a virgola mobile. Pertanto, i calcoli generano NAN o INFINITY, piuttosto che un'eccezione. Se vuoi eccezioni, puoi usare la funzione _controlfp_s su Windows per smascherare il punto mobile. eccezioni

Il seguente codice genera l'eccezione. Compilato ed eseguito con VS2010, configurazione Win32.

#include <float.h> 

int main() 
{ 
    _controlfp_s(NULL, 0, _MCW_EM); // enable all floating point exceptions 

    float n = 0; 
    float f= 0.0f/n; 

    return 0; 
} 
+0

Perché non guardare '' invece? – Deduplicator

+0

puoi darmi una prova per il reclamo? "le librerie di runtime C++ mascherano tutte le eccezioni a virgola mobile" così posso votare su –

+0

@KickButtowski, codice aggiornato. – Matt

0

è necessario sapere che la divisione a zero è consentito con i galleggianti quindi questo:

1.0/0.0 

è uguale a infinito e questo:

1.0/-0.0 

è uguale a infinito negativo (-0.0 è zero negativo come 1/0- in matematica) e questo:

0.0/0.0 

è NAN che significa non un numero, questo è esattamente indeterminato nell'abbreviazione matematica. che è con i galleggianti, ma interi getterà un errore di runtime, si può chiedere perché, è a causa di come galleggianti sono rappresentati in forma binaria, potete leggere qui:
http://floating-point-gui.de/formats/fp/
in C#, si può dire Double.PositiveInfinity, Double.NegativeInfinity e Double.NaN

Problemi correlati