Conversione di un double in un int in C #


103

Nel nostro codice abbiamo un double che dobbiamo convertire in un int.

double score = 8.6;
int i1 = Convert.ToInt32(score);
int i2 = (int)score;

Qualcuno può spiegarmi perché i1 != i2?

Il risultato che ottengo è che: i1 = 9e i2 = 8.


5
Math.Truncate(score)è un'intenzione più esplicitamente espressa di(int)score
Lu55

3
Ma Math.Truncate restituisce un doppio o un decimale, non un int
Sergioet

Risposte:


164

Perché i Convert.ToInt32turni:

Valore restituito: arrotondato all'intero con segno a 32 bit più vicino. Se il valore è a metà tra due numeri interi, viene restituito il numero pari; ovvero 4,5 viene convertito in 4 e 5,5 in 6.

... mentre il cast viene troncato :

Quando si converte da un valore double o float a un tipo integrale, il valore viene troncato.

Aggiornamento: vedere il commento di Jeppe Stig Nielsen di seguito per ulteriori differenze (che tuttavia non entrano in gioco se scoreè un numero reale come nel caso qui).


6
Il tuo link in realtà lo spiega meglio, e non è semplice come round vs truncate: Type: System.Int32 valore, arrotondato all'intero con segno a 32 bit più vicino. Se il valore è a metà tra due numeri interi, viene restituito il numero pari; cioè 4,5 viene convertito in 4 e 5,5 in 6.
ericosg

@ericosg: Sì, questo maschererebbe la differenza se scorefosse 8.5invece di 8.6. Ho aggiornato la risposta per includere le virgolette. Grazie per l'input.
Jon

5
E se scoreè NaNo è infinito o finito ma è al di fuori dell'intervallo di Int32, Convert.ToInt32verrà generata un'eccezione. Cast restituirà un int, ma non saprai quale (nella mia implementazione è Int32.MinValue) perché sei nel uncheckedcontesto. (Se sei nel checkedcontesto, anche il cast farà un'eccezione in questi casi.)
Jeppe Stig Nielsen

@JeppeStigNielsen: Grazie per l'input, ho aggiornato la risposta per menzionare anche questo.
Jon

Bello. Ma penso che il Doublenumero del tipo 10000000000.6(dieci miliardi di virgola sei) sia un numero "reale". Usare un cast intsu che darà un risultato strano (a meno che tu non sia nel checkedcontesto, ma probabilmente non lo sei).
Jeppe Stig Nielsen

13

Il cast ignorerà qualsiasi cosa dopo il punto decimale, quindi 8.6 diventa 8.

Convert.ToInt32(8.6) è il modo sicuro per assicurarti che il tuo doppio venga arrotondato al numero intero più vicino, in questo caso 9.


1
Domanda bonus - cosa succede se il valore del del doppio è troppo grande per spingere in int ? Cioè se è maggiore di int.MAX_VAL ?
Konrad Viltersten

1
@KonradViltersten genera un'eccezione Il valore era troppo grande o troppo piccolo per un Int32.
Vamsi

11

puoi arrotondare il tuo doppio e lanciare ist:

(int)Math.Round(myDouble);

4
la domanda era ora come fare i1 == i2. La domanda era sul perché non sono uguali. Downvoted.
Adam,

5

Nell'esempio fornito il tuo decimale è 8.6 . Se fosse stato 8.5 o 9.5, l'affermazione i1 == i2 avrebbe potuto essere vera. Infatti sarebbe stato vero per 8.5 e falso per 9.5.

Spiegazione:

Indipendentemente dalla parte decimale, la seconda istruzione int i2 = (int)scorescarterà la parte decimale e restituirà semplicemente la parte intera. Cosa abbastanza pericolosa da fare, poiché potrebbe verificarsi una perdita di dati.

Ora, per la prima affermazione, possono accadere due cose. Se la parte decimale è 5, cioè è a metà, è necessario prendere una decisione. Arrotondiamo per eccesso o per difetto? In C #, la classe Convert implementa l'arrotondamento del banchiere. Vedi questa risposta per una spiegazione più approfondita. In poche parole, se il numero è pari, arrotondare per difetto, se il numero è dispari, arrotondare per eccesso.

Ad esempio, considera:

        double score = 8.5;
        int i1 = Convert.ToInt32(score); // 8
        int i2 = (int)score;             // 8

        score += 1;
        i1 = Convert.ToInt32(score);     // 10
        i2 = (int)score;                 // 9

2

ToInt32 giri. Il cast su int elimina semplicemente il componente non intero.

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.