Come faccio a convertire un decimale in un int in C #?


227

Come faccio a convertire un decimale in un int?


11
Sarebbe utile sapere se si desidera arrotondare all'int più vicino o semplicemente rilasciare i numeri dopo il decimale (ovvero: arrotondare sempre per
difetto

128
onestamente non vedo il punto nel sottovalutare le domande autentiche. sì, la risposta potrebbe essere trovata su google MA non migliorerebbe la qualità del sito se le persone smettessero di chiudere ogni seconda domanda? non è come se questa domanda fosse spam o altro, e sono sicuro che sarebbe utile per molti nuovi
arrivati

Risposte:


268

Utilizzare Convert.ToInt32da mscorlibcome 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 .


10
Attenzione: Convert ha un comportamento sorprendente per una certa conversione ( nullvs. 0vs. ""). Consiglio di non usare mai Convert a meno che non sia assolutamente necessaria la sua flessibilità (ovvero in scenari tipicamente dinamici)
Eamon Nerbonne

1
-1 poiché non funzionerà con valori come decimal.MaxValue e decimal.MinValue e risulta in un valore OverflowException. Credo che @Will fornisce una risposta migliore qui stackoverflow.com/a/501165/39532
mezoid

8
Stai attento, perché Convert.ToInt32e Decimal.ToInt32comportati diversamente. Da MSDN: Decimal.ToInt32- Il valore restituito è la parte integrante del valore decimale; le cifre frazionarie vengono troncate . Convert.ToInt32- Restituisce il valore arrotondato all'intero con segno a 32 bit più vicino. Se il valore è a metà strada tra due numeri interi, viene restituito il numero pari; cioè 4.5 viene convertito in 4 e 5.5 convertito in 6.
vezucci,

67

Non puoi.

Bene, certo che potresti , tuttavia un int (System.Int32) non è abbastanza grande da contenere ogni possibile valore decimale.

Ciò significa che se si esegue il cast di un decimale più grande di int.MaxValue si verificherà un overflow e se il decimale è più piccolo di int.MinValue, sarà underflow.

Cosa succede in caso di underflow / overflow? Una delle due cose Se la tua build è deselezionata (ovvero, al CLR non importa se lo fai), la tua applicazione continuerà dopo il valore over / underflow, ma il valore in int non sarà quello che ti aspettavi. Ciò può portare a bug intermittenti e può essere difficile da correggere. Finirai la tua applicazione in uno stato sconosciuto che potrebbe causare la corruzione della tua applicazione da qualsiasi dato importante su cui sta lavorando. Non bene.

Se il tuo assieme è spuntato (proprietà-> build-> avanzato-> verifica la presenza di overflow / underflow aritmetici o l'opzione del compilatore / checked), il tuo codice genererà un'eccezione quando si verifica un under / overflow. Questo è probabilmente meglio di no; tuttavia l'impostazione predefinita per gli assiemi non è quella di verificare l'overflow / underflow.

La vera domanda è "cosa stai cercando di fare?" Senza conoscere le tue esigenze, nessuno può dirti cosa dovresti fare in questo caso, a parte l'ovvio: NON FARLO.

Se in particolare NON ti interessa, le risposte qui sono valide. Tuttavia, dovresti comunicare la tua comprensione del fatto che potrebbe verificarsi un overflow e che non importa avvolgendo il codice cast in un blocco non selezionato

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

In questo modo le persone che arrivano dietro di te capiscono che non ti interessa, e se in futuro qualcuno cambierà le tue build in / controllerà, il tuo codice non si romperà inaspettatamente.

Se tutto ciò che vuoi fare è rilasciare la parte frazionaria del numero, lasciando la parte integrale, puoi usare 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 con Decimal.Truncate che Math.Truncate, poiché quest'ultimo accetta anche i doppi e quindi può essere compreso per essere in grado di troncare i numeri pari che non sono base 10, al contrario di Decimal.Truncate, che è un vero troncamento di un numero base 10.
Brian,

7
I contesti non controllati non si applicano ai decimali; le operazioni sui decimali genereranno OverflowExceptions a prescindere.
Dave,

46
int i = (int)d;

ti darà il numero arrotondato per difetto.

Se si desidera arrotondare al numero pari più vicino (ovvero> 0,5 arrotonderà per eccesso) è possibile utilizzare

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

In generale è possibile eseguire il cast tra tutti i tipi numerici in C #. Se non ci sono informazioni che andranno perse durante il cast, puoi farlo implicitamente:

int i = 10;
decimal d = i;

anche se puoi ancora farlo esplicitamente se desideri:

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

Tuttavia, se stai per perdere informazioni attraverso il cast, devi farlo esplicitamente (per mostrare che sei consapevole che potresti perdere informazioni):

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

Qui stai perdendo il ".5". Questo può andare bene, ma devi essere esplicito al riguardo e fare un cast esplicito per dimostrare che potresti perdere le informazioni.


1
In realtà vuoi MidpointRounding.AwayFromZero se vuoi> * .5 arrotondare sempre in base alla mia esperienza provando il codice sopra guardando l'output di esempio qui: msdn.microsoft.com/en-us/library/…
Elijah Lofgren

@ElijahLofgren Dipende in qualche modo: se stai facendo statistiche, ToEvendovrebbe prevenire la deriva statistica. Se tuttavia operi con articoli o denaro addebitabili, AwayFromZerosembra la scelta giusta.
mbx,

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

Questo dovrebbe funzionare bene.


Attento, con una conversione esplicita le informazioni potrebbero andare perse.
Fedro

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


8

System.Decimalimplementa l' IConvertableinterfaccia, che ha un ToInt32()membro.

La chiamata System.Decimal.ToInt32()funziona per te?


2
Dalla documentazione : "Questa API supporta l'infrastruttura .NET Framework e non deve essere utilizzata direttamente dal tuo codice". Perché non usare Convert.ToInt32?
H.Wolper,

7

Un trucco accurato per l'arrotondamento veloce è l'aggiunta di 0,5 prima di lanciare il tuo decimale su un int.

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

Va ancora i=10, ma

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

Arrotonderebbe per quello i=11.


5
Perché preoccuparsi di farlo quando c'è Math.Floor e Math.Ceiling?
Badaro,

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

1
E se il valore decimale fosse ad es. -9.3?
supercat

6

Preferisco usare Math.Round , Math.Floor , Math.Ceiling o Math.Truncate per impostare esplicitamente la modalità di arrotondamento nel modo appropriato.

Si noti che restituiscono anche tutti i decimali, poiché Decimal ha un intervallo di valori più ampio rispetto a un Int32, quindi sarà comunque necessario eseguire il cast (e verificare la presenza di overflow / underflow).

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


6

Arrotondare un decimale all'intero più vicino

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

quando a = 49.9, allorab = 50

quando a = 49.5, allorab = 50

quando a = 49.4, quindi b = 49ecc.


0

Trovo che l'operatore di casting non funzioni se hai un decimale inscatolato (cioè un valore decimale all'interno di un tipo di oggetto). Convert.ToInt32 (decimale come oggetto) funziona bene in questo caso.

Questa situazione si presenta quando si recuperano i valori IDENTITY / 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 Conversioni di unboxing


2
Aggiungendone di più come riferimento: questo perché puoi solo decomprimere lo stesso tipo originale. Qui SELECT SCOPE_IDENTITY()ritorna numeric(38, 0)che si traduce in decimal.NET. foo.ExecuteScalar()restituisce un decimalbox in quanto objectnon può essere trasmesso direttamente a un int. (int)(decimal)foo.ExecuteScalar()o Convert.ToInt32(foo.ExecuteScalar())avrebbe funzionato.
Rageit,

0

Nessuna risposta sembra avere a che fare con OverflowException / UnderflowException che proviene dal tentativo di convertire un decimale al di fuori dell'intervallo di int.

int intValue = (int)Math.Max(int.MinValue, Math.Min(int.MaxValue, decimalValue));

Questa soluzione restituirà il valore int massimo o minimo possibile se il valore decimale è al di fuori dell'intervallo int. Potresti voler aggiungere alcuni arrotondamenti con Math.Round, Math.Ceiling o Math.Floor per quando il valore è compreso nell'intervallo int.

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.