2009-02-01 19 views
183

Come si converte un decimale in un intero?Come si converte un numero decimale in un numero intero in C#?

+9

Sarebbe utile sapere se si voleva arrotondare al più vicino int o semplicemente cadere i numeri dopo la virgola (es: arrotondare sempre verso il basso) – Dinah

+112

Sinceramente non vedo il punto in downvoting domande genuine. sì, la risposta potrebbe essere trovata su google, ma non sarebbe solo migliorare la qualità del sito se la gente smettesse di chiudere ogni seconda domanda? non è come se questa domanda fosse spam o altro, e sono sicuro che sarebbe utile per molti new-comer di C# –

risposta

228

Usa Convert.ToInt32 da mscorlib come in

decimal value = 3.14m; 
int n = Convert.ToInt32(value); 

Vedi MSDN. Puoi anche usare Decimal.ToInt32. Ancora una volta, vedi MSDN. Infine, puoi eseguire un cast diretto come in

decimal value = 3.14m; 
int n = (int) value; 

che utilizza l'operatore di cast esplicito. Vedi MSDN.

+8

Attenzione: Convert ha alcuni comportamenti sorprendenti per certe conversioni ('null' vs.' 0' vs. ' ""'). Raccomanderei di non utilizzare mai Converti a meno che non sia assolutamente necessario la sua flessibilità (ad esempio in scenari dinamicamente tipizzati) –

+1

-1 poiché non funzionerà con valori come decimal.MaxValue e decimal.MinValue e restituisce un 'OverflowException'. Credo che @Will fornisca una risposta migliore qui http://stackoverflow.com/a/501165/39532 – mezoid

+2

Fai attenzione, perché 'Convert.ToInt32' e' Decimal.ToInt32' si comportano diversamente. Da MSDN: 'Decimal.ToInt32' - Il valore di ritorno è la parte integrale del valore decimale; le cifre frazionarie sono ** troncate **. 'Convert.ToInt32' - Restituisce il valore ** arrotondato ** al numero intero con segno a 32 bit più vicino. Se il valore è a metà strada tra due numeri interi, viene restituito il numero pari; ovvero, 4.5 viene convertito in 4 e 5.5 viene convertito in 6. – vezucci

8

System.Decimal implementa l'interfaccia IConvertable, che ha un membro ToInt32().

Il telefono System.Decimal.ToInt32() funziona per te?

+1

Da [la documentazione] (https://msdn.microsoft.com/en-us/library/bb350799 (v = vs.110) .aspx) : "Questa API supporta l'infrastruttura .NET Framework e non è progettata per essere utilizzata direttamente dal codice". Perché non utilizzare Convert.ToInt32? –

18
decimal d = 2; 
int i = (int) d; 

Questo dovrebbe funzionare bene.

+0

Attenzione, con una conversione esplicita le informazioni potrebbero andare perse. – Phaedrus

+18

Quando si converte da decimale a int, le informazioni saranno quasi sempre perse, ma credo che sia un po 'il punto. – Dinah

38
int i = (int)d; 

ti darà il numero arrotondato.

Se si desidera arrotondare al numero pari più vicino (cioè> 0,5 sarà arrotondare) è possibile utilizzare

int i = (int)Math.Round(d, MidpointRounding.ToEven); 

In generale si può lanciare tra tutti i tipi numerici in C#. Se non vi sono informazioni che verranno persi durante il lancio si può fare in modo implicito:

int i = 10; 
decimal d = i; 

anche se è ancora possibile farlo in modo esplicito, se lo si desidera:

int i = 10; 
decimal d = (decimal)i; 

Tuttavia, se avete intenzione di essere perdita di informazioni attraverso il cast è necessario farlo in modo esplicito (per mostrare siete a conoscenza che si può perdere informazioni):

decimal d = 10.5M; 
int i = (int)d; 

Qui si stanno perdendo il" .5" . Questo può andar bene, ma devi essere esplicito a riguardo e fare un cast esplicito per mostrare che potresti perdere le informazioni.

8

Un trucco perfetto per arrotondare rapidamente è aggiungere .5 prima di trasmettere il valore decimale a un valore int.

decimal d = 10.1m; 
d += .5m; 
int i = (int)d; 

lascia ancora i=10, ma

decimal d = 10.5m; 
d += .5m; 
int i = (int)d; 

Sarebbe arrotondare in modo che i=11.

+5

Perché preoccuparsi di fare questo quando c'è Math.Floor e Math.Ceiling? – Badaro

+0

All'epoca ero abbastanza nuovo in C# e per qualche motivo non mi ero reso conto che queste funzioni esistevano. In realtà è un trucco che ho imparato da C/C++, dove ovviamente era più utile. – DeadlyBrad42

+1

Cosa succede se il valore decimale era, ad es. -9.3? – supercat

64

Non è possibile.

Beh, naturalmente è possibile che sia, tuttavia un int (System.Int32) non è abbastanza grande da contenere ogni possibile valore decimale.

Ciò significa che se si esegue un decimale superiore a int.MaxValue si verificherà un overflow e se il valore decimale è inferiore a int.MinValue, sarà inferiore.

Cosa succede quando si sotto/troppo pieno? Una delle due cose. Se la costruzione non è selezionata (vale a dire, il CLR non importa se si fa), l'applicazione continuerà dopo che il valore sopra/underflow, ma il valore nel int non sarà quello che vi aspettavate. Questo può portare a bug intermittenti e potrebbe essere difficile da risolvere. Finirai con la tua applicazione in uno stato sconosciuto che potrebbe portare la tua applicazione a corrompere qualsiasi dato importante su cui sta lavorando. Non bene.

Se l'assembly è selezionato (proprietà-> build-> advanced-> verifica per overflow/underflow aritmetico o l'opzione del compilatore/checked), il codice genererà un'eccezione quando si verifica un under/overflow. Probabilmente è meglio di no; tuttavia, l'impostazione predefinita per gli assembly non è la verifica dell'over/underflow.

la vera domanda è "che cosa stai cercando di fare?" Senza conoscere le vostre esigenze, nessuno può dire che cosa si dovrebbe fare in questo caso, a parte l'ovvio: non fatelo.

Se specificamente non si cura, le risposte qui sono validi. Tuttavia, si dovrebbe comunicare la comprensione che un overflow potrebbe verificarsi e che non importa avvolgendo il codice di fusione in un blocco incontrollato

unchecked 
{ 
    // do your conversions that may underflow/overflow here 
} 

In questo modo le persone che vengono dietro di voi capisce non lo fai cura, e se in futuro qualcuno cambia la costruisce a/controllato, il codice non si rompe inaspettatamente.

Se tutto ciò che si vuole fare è rilasciare la parte frazionaria del numero, lasciando la parte integrale, è possibile utilizzare Math.Truncate.

decimal actual = 10.5M; 
decimal expected = 10M; 
Assert.AreEqual(expected, Math.Truncate(actual)); 
+3

Anche se sospetto che siano la stessa cosa sotto il cofano se l'input è un decimale, mi sento più a mio agio usando Decimal.Truncate di Math.Truncate, dal momento che quest'ultimo accetta anche il doppio e quindi può essere compreso per essere in grado di troncare numeri che non sono base 10, al contrario di Decimal.Truncate, che è un vero troncamento di un numero di base 10. – Brian

+6

I contesti non selezionati non si applicano ai decimali; le operazioni su decimali genereranno OverflowExceptions a prescindere. – Dave

+0

@dave Damnit, hai ragione. BRB, ECMA. – Will

6

Io preferisco usare Math.Round, Math.Floor, Math.Ceiling o Math.Truncate per impostare in modo esplicito la modalità di arrotondamento a seconda dei casi.

Si noti che tutti restituiscono anche Decimal - poiché Decimal ha un intervallo di valori più ampio di un Int32, quindi sarà ancora necessario eseguire il cast (e verificare l'overflow/underflow).

checked { 
    int i = (int)Math.Floor(d); 
} 
0

Trovo che l'operatore di fusione non funziona se si dispone di un numero decimale in scatola (vale a dire un valore decimale all'interno di un tipo di oggetto). Convert.ToInt32 (decimale come oggetto) funziona correttamente in questo caso.

Questa situazione si presenta quando si recuperano i valori IDENTITÀ/autonumber dal database:

SqlCommand foo = new SqlCommand("INSERT INTO...; SELECT SCOPE_IDENTITY()", conn); 
int ID = Convert.ToInt32(foo.ExecuteScalar()); // works 
int ID = (int)foo.ExecuteScalar();    // throws InvalidCastException 

Vedi 4.3.2 Unboxing conversions

+2

Aggiungendo altro a esso per riferimento: è perché è possibile solo annullare la registrazione allo stesso tipo originale. Qui 'SELECT SCOPE_IDENTITY()' restituisce 'numeric (38, 0)' che si traduce in 'decimal' di .NET. 'foo.ExecuteScalar()' restituisce un 'decimale' in scatola come' oggetto' che non può essere castato direttamente in un 'int'. '(int) (decimale) foo.ExecuteScalar()' o 'Convert.ToInt32 (foo.ExecuteScalar())' funzionerebbe. – rageit

5

decimale d = 5.5;

int i = decimal.ToInt32(d);// you will get i = 5 

ref: link text

3

arrotondamento decimale al numero intero più vicino

decimal a ; 
int b = (int)(a + 0.5m); 

quando a = 49.9, quindi b = 50

quando a = 49.5, quindi b = 50

quando a = 49.4, quindi b = 49 ecc

Problemi correlati