Konwersja double na int w C #

103

W naszym kodzie mamy double, który musimy przekonwertować na int.

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

Czy ktoś może mi wyjaśnić, dlaczego i1 != i2?

Wynik, który otrzymuję jest taki: i1 = 9i i2 = 8.

Wouter Dorgelo
źródło
5
Math.Truncate(score)jest wyraźniej wyrażony niż(int)score
Lu55
3
Ale Math.Truncate zwraca podwójną lub dziesiętną, a nie int
Sergioet

Odpowiedzi:

165

Ponieważ Convert.ToInt32rundy:

Wartość zwracana: zaokrąglona do najbliższej 32-bitowej liczby całkowitej ze znakiem. Jeśli wartość jest w połowie między dwiema liczbami całkowitymi, zwracana jest liczba parzysta; to znaczy 4,5 jest konwertowane na 4, a 5,5 jest konwertowane na 6.

... podczas gdy obsada się obcina :

Podczas konwertowania wartości typu double lub float na typ całkowity wartość jest obcinana.

Aktualizacja: Zobacz komentarz Jeppe Stiga Nielsena poniżej, aby poznać dodatkowe różnice (które jednak nie mają znaczenia, jeśli scorejest liczbą rzeczywistą, jak ma to miejsce w tym przypadku).

Jon
źródło
6
Twój link właściwie wyjaśnia to najlepiej i nie jest tak prosty, jak round vs truncate: Type: System.Int32 wartość zaokrąglona do najbliższej 32-bitowej liczby całkowitej ze znakiem. Jeśli wartość jest w połowie między dwiema liczbami całkowitymi, zwracana jest liczba parzysta; oznacza to, że 4,5 jest konwertowane na 4, a 5,5 jest konwertowane na 6.
ericosg
@ericosg: Tak, to maskowałoby różnicę, gdyby scorebyło 8.5zamiast 8.6. Zaktualizowałem odpowiedź, aby zawierała cytaty. Dzięki za wkład.
Jon
5
A jeśli scorejest NaN, nieskończoność lub skończona, ale poza zakresem Int32, to Convert.ToInt32zgłosi wyjątek. Cast zwróci an int, ale nie będziesz wiedział, który z nich (w mojej implementacji to jest Int32.MinValue), ponieważ jesteś w uncheckedkontekście. (Jeśli jesteś w checkedkontekście, obsada również rzuci wyjątek w tych przypadkach).
Jeppe Stig Nielsen
@JeppeStigNielsen: Dzięki za wkład, zaktualizowałem odpowiedź, aby również o tym wspomnieć.
Jon
Miły. Ale myślę, że Doubletypowa liczba 10000000000.6(dziesięć miliardów przecinek sześć) jest liczbą „rzeczywistą”. Użycie rzutowania intna to da dziwny wynik (chyba że jesteś w checkedkontekście, ale prawdopodobnie tak nie jest).
Jeppe Stig Nielsen
13

Rzutowanie zignoruje wszystko po przecinku, więc 8.6 zmieni się na 8.

Convert.ToInt32(8.6) to bezpieczny sposób na zaokrąglenie podwójnej liczby do najbliższej liczby całkowitej, w tym przypadku 9.

neilgmacy
źródło
1
Pytanie bonusowe - co się stanie, jeśli wartość double jest zbyt duża, aby wcisnąć int ? To znaczy, jeśli jest wyższy niż int.MAX_VAL ?
Konrad Viltersten
1
@KonradViltersten Zgłasza wyjątek Wartość była za duża lub za mała dla Int32.
Vamsi
11

możesz zaokrąglić swoją dublet i rzucić ist:

(int)Math.Round(myDouble);
David
źródło
4
pytanie brzmiało teraz, jak to zrobić i1 == i2. Pytanie dotyczyło tego , dlaczego nie są równi. Głosowano w dół.
Adam
5

W podanym przykładzie Twój dziesiętny to 8,6 . Gdyby było 8.5 lub 9.5, stwierdzenie i1 == i2 mogłoby być prawdziwe. W rzeczywistości byłoby to prawdą w przypadku wersji 8.5, a fałszem w przypadku wersji 9.5.

Wyjaśnienie:

Niezależnie od części dziesiętnej, drugie stwierdzenie, int i2 = (int)score odrzuci część dziesiętną i po prostu zwróci część całkowitą. Dość niebezpieczna rzecz, ponieważ może dojść do utraty danych.

W przypadku pierwszego stwierdzenia mogą się wydarzyć dwie rzeczy. Jeśli część dziesiętna wynosi 5, to znaczy jest w połowie, należy podjąć decyzję. Czy zaokrąglamy w górę czy w dół? W języku C # klasa Convert implementuje zaokrąglanie bankierów. Zobacz to odpowiedź, aby uzyskać głębsze wyjaśnienie. Mówiąc najprościej, jeśli liczba jest parzysta, zaokrąglij w dół, jeśli liczba jest nieparzysta, zaokrąglij w górę.

Np. Rozważ:

        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
Evdzhan Mustafa
źródło
2

ToInt32 rundy. Rzutowanie na int po prostu odrzuca składnik nie będący liczbą całkowitą.


źródło