2010-05-29 7 views
33

Che succede, comunque? Faccio un semplice moltiplicazione:Non dovrebbe causare un Overflow? Non è così!

Int64 x = 11111111111; 
Int64 y = 11111111111; 
Int64 z = x * y; 

E alla fine della moltiplicazione, z mostra un valore di:

-5670418394979206991

Questo ha chiaramente traboccato, ma nessuna eccezione è sollevata. Vorrei che ne venisse sollevato uno, ma ...

Si noti che questo è su Windows Phone 7, ma non penso che questo abbia alcun rapporto con il problema. O lo fa?

risposta

43

È possibile utilizzare un blocco controllato come sottolineato già da altre risposte:

checked 
{ 
    long x = 11111111111; 
    long y = 11111111111; 
    long z = checked(x * y); 
    // ... 
} 

che si traduce in un'eccezione:

OverflowException: operazione aritmetica ha comportato un overflow.

Se si sta solo facendo una sola operazione in cui è necessario il controllo è possibile utilizzare un checked expression invece:

long x = 11111111111; 
long y = 11111111111; 
long z = checked(x * y); 

È inoltre possibile impostare il /checked compiler option di avere il default controllato.

Per impostare questa opzione del compilatore nell'ambiente di sviluppo di Visual Studio:

  1. finestra di dialogo Apri Pagine delle proprietà del progetto. Per dettagli, vedere Setting Visual C# Project Properties.
  2. Fare clic sulla cartella Proprietà di configurazione.
  3. Fare clic sulla pagina di proprietà Build.
  4. Modificare Verifica proprietà di overflow/underflow aritmetico.

Se si modifica l'impostazione predefinita per controllare è possibile utilizzare i blocchi non controllati o espressioni per ottenere di nuovo il comportamento incontrollato.

+25

Si noti che il motivo per cui è deselezionata l'impostazione predefinita è perché (1) il 99% del tempo dell'aritmetica dei numeri interi non è affatto vicino ai limiti e (2) l'aritmetica verificata è SEMPRE più lenta. Questo è uno dei rari casi in cui il design di C# sceglie pericolosi per default per motivi di prestazioni. –

+0

Il jitter x86 utilizza un jno semplice, la previsione del ramo è sempre buona, non può costare più di un singolo ciclo. –

+0

Non che fosse necessariamente rilevante per il design di C# ma in questo caso specifico stiamo parlando di ARM. Il comportamento del jitter x86 è piuttosto accademico – Stewart

26

Check it:

checked 
{ 
    Int64 x = 11111111111; 
    Int64 y = 11111111111; 
    Int64 z = x * y; 
} 
+6

Bingo! Impara qualcosa di nuovo ogni giorno, lo faccio! Grazie. E grazie a Dio per SO. – Cyberherbalist

8

Prova:

checked 
{ 
    Int64 x = 11111111111; 
    Int64 y = 11111111111; 
    Int64 z = x * y; 
} 
8

compilatore presuppone che si vuole fare in quel modo e procedere con l'overflow. Se l'overflow deve essere considerato come eccezione per l'operazione, avvolgere l'operazione intorno a checked e genererà un'eccezione in fase di runtime.

checked 
{ 
    Int64 x = 11111111111; 
    Int64 y = 11111111111; 
    Int64 z = x * y; 
} 

System.OverflowException: Un'eccezione di tipo System.OverflowException era gettato.

Problemi correlati