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.


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).


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.


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);

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

2

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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.