Перетворення двійника в int в C #


103

У нашому коді є дубль, який нам потрібно перетворити на int.

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

Хтось може мені пояснити, чому i1 != i2?

Результат, який я отримую, такий: i1 = 9і i2 = 8.


5
Math.Truncate(score)є більш чітко вираженим наміром, ніж(int)score
Lu55

3
Але Math.Truncate повертає подвійний чи десятковий, а не інт
Sergioet

Відповіді:


164

Тому що Convert.ToInt32тури:

Повернене значення: округляється до найближчого 32-бітного цілого числа, підписаного. Якщо значення знаходиться на півдорозі між двома цілими числами, повертається парне число; тобто 4,5 перетворюється на 4, а 5,5 перетворюється на 6.

... в той час як литий стриг :

Коли ви перетворюєте з подвійного або плаваючого значення в цілісний тип, це значення врізається.

Оновлення: див. Коментар Джеппе Стіга Нільсена нижче щодо додаткових розбіжностей (які, однак, не вступають у дію, якщо scoreце справжнє число, як у випадку).


6
Ваше посилання насправді пояснює це найкраще, і це не так просто, як круглий проти усікання: Тип: Значення System.Int32, округлене до найближчого 32-бітного цілого числа, підписаного. Якщо значення знаходиться на півдорозі між двома цілими числами, повертається парне число; тобто 4,5 перетворюється на 4, а 5,5 перетворюється на 6.
ericosg

@ericosg: Так, що б маскувати різницю , якщо scoreбули 8.5замість 8.6. Я оновив відповідь, щоб включити цитати. Дякуємо за вклад.
Джон

5
І якщо scoreце NaNабо нескінченність або скінченність, але виходить за межі діапазону Int32, тоді Convert.ToInt32викине виняток. Cast поверне int, але ви не знаєте, який саме (на мою реалізацію це Int32.MinValue), тому що ви знаходитесь в uncheckedконтексті. (Якщо ви знаходитесь в checkedконтексті, акторський склад буде винятком і у цих випадках.)
Jeppe Stig Nielsen

@JeppeStigNielsen: Дякую за вклад, я оновив відповідь, щоб згадати і про це.
Джон

Приємно. Але я думаю, що Doubleтип типу 10000000000.6(десять мільярдів балів шість) є "реальним" числом. Використання ролі intна це дасть дивний результат (якщо ви не в checkedконтексті, але ви, мабуть, не так).
Джеппе Стіг Нільсен

13

Кастинг ігнорує що-небудь після десяткової крапки, тому 8,6 стає 8.

Convert.ToInt32(8.6) це безпечний спосіб забезпечити округлення вашого подвійного до найближчого цілого числа, в цьому випадку 9.


1
Питання про бонус - що станеться, якщо значення подвійного буде занадто великим, щоб натиснути на int ? Тобто, якщо він вище, ніж int.MAX_VAL ?
Конрад Вільтерстен

1
@KonradViltersten Викидає Значення
Вамсі

11

ви можете округлити ваш подвійний і кинути ist:

(int)Math.Round(myDouble);

4
питання тепер було, як це зробити i1 == i2. Питання полягало у тому, чому вони не рівні. Захищений.
Адам

5

У наведеному прикладі ваш десятковий знак - 8,6 . Якби це було 8,5 або 9,5, твердження i1 == i2, можливо, було б істинним. Інфакт був би правдою для 8,5, а помилковим - для 9,5.

Пояснення:

Незалежно від десяткової частини, другий вислів int i2 = (int)scoreвідкине десяткову частину і просто поверне вам цілу частину. Досить небезпечно робити, оскільки може статися втрата даних.

Тепер для першого твердження можуть статися дві речі. Якщо десяткова частина дорівнює 5, тобто вона знаходиться на півдорозі, слід прийняти рішення. Ми обходимо вгору чи вниз? У C # клас конвертувати реалізує заокруглення банкіра. Дивіться цю відповідь для більш глибокого пояснення. Простіше кажучи, якщо число парне, округніть вниз, якщо число непарне, округляйте вгору.

Наприклад, врахуйте:

        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 турів. Кастинг до int просто викидає не цілий компонент.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.