Як перетворити десятковий знак в int в C #?


227

Як перетворити десятковий знак в цілий?


11
Було б корисно дізнатися, чи хочете ви округлити найближчий int або просто відкинути цифри після десяткових (тобто: завжди округлюйте вниз)
Діна,

128
я, чесно кажучи, не бачу сенсу у відмові від справжніх питань. так, відповідь можна знайти в Google, Але хіба це не просто поліпшить якість сайту, якби люди перестали закривати кожне друге запитання? це не так, як це питання - це спам чи що-небудь, і я впевнений, що це може бути корисно багатьом новачкам в c #
jay_t55

Відповіді:


268

Використовувати Convert.ToInt32від mscorlibяк в

decimal value = 3.14m;
int n = Convert.ToInt32(value);

Див. MSDN . Ви також можете використовувати Decimal.ToInt32. Знову див. MSDN . Нарешті, ви можете зробити прямий склад як у

decimal value = 3.14m;
int n = (int) value;

який використовує оператор явного лиття. Див. MSDN .


10
Бережіться: Перетворити мають деякі дивовижні поведінки для певного перетворення ( nullпроти 0проти ""). Я рекомендую ніколи не використовувати Convert, якщо вам абсолютно не потрібна його гнучкість (тобто в динамічно набраних сценаріях)
Eamon Nerbonne

1
-1, оскільки це не буде працювати для значень, таких як decimal.MaxValue і decimal.MinValue і призводить до OverflowException. Я вважаю , що @Will забезпечує кращий відповідь тут stackoverflow.com/a/501165/39532
mezoid

8
Будьте обережні, тому що Convert.ToInt32і Decimal.ToInt32поводьтесь інакше. Від MSDN: Decimal.ToInt32- повернене значення є невід'ємною частиною десяткового значення; дробові цифри усічені . Convert.ToInt32- Повернене значення округлюється до найближчого 32-бітного цілого числа. Якщо значення знаходиться на півдорозі між двома цілими числами, повертається парне число; тобто 4,5 перетворюється на 4, а 5,5 перетворюється на 6.
vezucci

67

Ви не можете.

Ну, звичайно, ви могли , однак int (System.Int32) не є достатньо великим, щоб вмістити всі можливі десяткові значення.

Це означає, що якщо ви подасте десятковий розмір, більший за int.MaxValue, ви переповниться, а якщо десятковий розмір менший за int.MinValue, він переллється.

Що відбувається, коли ви перебуваєте під / переповненням? Одна з двох речей. Якщо ваша збірка відмічена (тобто CLR не хвилює, чи є), ваш додаток продовжуватиметься після того, як значення перевищить / переливає, але значення в int не буде таким, яке ви очікували. Це може призвести до непостійних помилок і може бути важко виправити. Ви закінчите свою заявку в невідомому стані, що може призвести до пошкодження вашої програми будь-яких важливих даних, на яких вона працює. Не добре.

Якщо ваша збірка перевірена (властивості-> збірка-> розширений-> перевірка на арифметичне переповнення / підводка або параметр / перевірений компілятор), ваш код видасть виняток, коли має місце недолік / переповнення. Це, мабуть, краще, ніж ні; однак за замовчуванням для збірок не є перевірка на перевищення / перелив.

Справжнє питання - "що ти намагаєшся зробити?" Не знаючи ваших вимог, ніхто не може сказати вам, що ви повинні робити в цьому випадку, окрім очевидного: НЕ РОБИТИ.

Якщо вас конкретно НЕ хвилює, відповіді тут справедливі. Однак, ви повинні повідомити про своє розуміння того, що може виникнути переповнення, і що це не має значення, загорнувши свій код для відтворення в неперевірений блок

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

Таким чином, люди, що йдуть за вами, розуміють, що вам все одно, і якщо в майбутньому хтось змінить вашу конструкцію на / перевірив, ваш код не стане несподівано порушеним.

Якщо все, що ви хочете зробити, це скинути дробову частину числа, залишивши невід'ємну частину, ви можете використовувати Math.Truncate.

decimal actual = 10.5M;
decimal expected = 10M;
Assert.AreEqual(expected, Math.Truncate(actual));

3
Хоча я підозрюю, що це одне і те ж саме під кришкою, якщо вхід є десятковим, мені зручніше використовувати Decimal.Truncate, ніж Math.Truncate, оскільки останній також приймає подвійні і, таким чином, можна зрозуміти, щоб мати можливість усікати парні числа які не є базовою 10, на відміну від Decimal.Truncate, що є справжнім усіченням базового числа 10.
Брайан

7
Неперевірений контекст не застосовується до десяткових знаків; Операції над десятковими кодами будуть кидати OverflowExceptions незалежно.
Дейв

46
int i = (int)d;

дасть вам число, округлене вниз.

Якщо ви хочете округлити до найближчого парного числа (тобто> .5 буде округлювати), ви можете використовувати

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

Як правило, ви можете додавати між усіма числовими типами в C #. Якщо під час виступу немає інформації, яка буде втрачена, ви можете це зробити неявно:

int i = 10;
decimal d = i;

хоча ви все одно можете це зробити явно, якщо бажаєте:

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

Однак, якщо ви збираєтеся втрачати інформацію через трансляцію, ви повинні зробити це явно (щоб показати, що ви знаєте, що ви можете втрачати інформацію):

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

Тут ви втрачаєте ".5". Це може бути добре, але ви повинні бути чіткими щодо цього і зробити чіткий склад, щоб показати, що знаєте, що можете втратити інформацію.


1
Ви на самому справі хочете MidpointRounding.AwayFromZero , якщо ви хочете> * .5 завжди облави на основі мого досвіду , що намагається з коду вище , дивлячись на зразок продукції тут: msdn.microsoft.com/en-us/library / ...
Ілля Lofgren

@ElijahLofgren Це якось залежить: Якщо ви займаєтесь статистикою, ToEvenслід запобігати дрейфу статистики. Якщо ви оперуєте платними предметами чи грошима, це AwayFromZeroздається правильним вибором.
mbx

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

Це має спрацювати чудово.


Обережно, з явною інформацією про перетворення може бути втрачено.
Федр

21
При перетворенні від десяткових до int інформація майже завжди буде втрачена, але я вважаю, що це справді важливо.
Діна


8

System.Decimalреалізує IConvertableінтерфейс, який маєToInt32() член.

Чи System.Decimal.ToInt32()працює для вас дзвінок ?


2
З документації : "Цей API підтримує інфраструктуру .NET Framework і не призначений для використання безпосередньо з вашого коду". Чому б не використовувати Convert.ToInt32?
Х.Волпер

7

Акуратний трюк для швидкого округлення - додати .5 перед тим, як подати десятковий знак до цілого.

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

Ще залишає i=10, але

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

Округлили б так, що i=11.


5
Навіщо турбуватися робити це, коли є Math.Floor і Math.Ceiling?
Бадаро

У той час я був досить новинкою в C #, і я чомусь не усвідомлював, що ці функції існують. Це насправді трюк, який я навчився від C / C ++, де він був, очевидно, кориснішим.
DeadlyBrad42

1
Що робити, якщо десяткове значення було, наприклад, -9,3?
supercat

6

Я вважаю за краще використовувати Math.Round , Math.Floor , Math.Ceiling або Math.Truncate щоб явно встановити режим округлення у відповідних випадках.

Зауважте, що всі вони також повертають десятичну кількість - оскільки у Decimal є більший діапазон значень, ніж у Int32, тому вам все одно потрібно буде робити передачу (і перевірити наявність переливу / переливання).

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


6

Округлення десяткової точки до найближчого цілого числа

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

коли a = 49.9 , тоb = 50

коли a = 49.5 , тоb = 50

коли a = 49.4, то b = 49і т.д.


0

Я вважаю, що оператор кастингу не працює, якщо у вас є десятичне поле (тобто десяткове значення всередині типу об’єкта). Convert.ToInt32 (десятковий як об'єкт) працює в цьому випадку добре.

Ця ситуація виникає під час отримання значень IDENTITY / AUTONUMBER з бази даних:

SqlCommand foo = new SqlCommand("INSERT INTO...; SELECT SCOPE_IDENTITY()", conn);
int ID = Convert.ToInt32(foo.ExecuteScalar());  // works
int ID = (int)foo.ExecuteScalar();              // throws InvalidCastException

Див. 4.3.2 Розблокування конверсій


2
Додавання до нього більше для довідки: це тому, що ви можете розблокувати лише той же оригінальний тип. Тут SELECT SCOPE_IDENTITY()повертається, numeric(38, 0)що перекладається на decimal.NET. foo.ExecuteScalar()повертає decimalкоробку, objectяка не може бути передана безпосередньо на int. (int)(decimal)foo.ExecuteScalar()або Convert.ToInt32(foo.ExecuteScalar())працювали б.
rageit

0

Здається, жодна відповідь не стосується OverflowException / UnderflowException, який виникає при спробі перетворення десяткової, що знаходиться поза діапазоном int.

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

Це рішення поверне максимальне або мінімальне можливе значення int, якщо десяткове значення знаходиться поза діапазоном int. Ви можете додати кілька округлення за допомогою Math.Round, Math.Ceiling або Math.Floor, коли значення знаходиться в межах діапазону int.

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