2009-02-01 3 views
183

Как преобразовать десятичное число в int?Как преобразовать десятичное число в int в C#?

+9

Было бы полезно знать, хотите ли вы округление до ближайшего междунар или просто падение числа после запятой (т.е. всегда округлять вниз) – Dinah

+112

я честно не вижу смысл в downvoting подлинных вопросов. да, ответ можно найти в google. Но разве это не улучшило бы качество сайта, если бы люди перестали закрывать каждый второй вопрос? это не так, как этот вопрос - спам или что-то еще, и я уверен, что это было бы полезно для многих новичков в C# –

ответ

228

Использование 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.

+8

Остерегайтесь: Convert имеет некоторые неожиданные действия для определенного преобразования ('null' vs.' 0' vs. ' ""'). Я бы рекомендовал никогда не использовать Convert, если вам не нужна его гибкость (т. Е. В динамически типизированных сценариях) –

+1

-1, поскольку это не будет работать для таких значений, как decimal.MaxValue и decimal.MinValue, и приводит к 'OverflowException'. Я считаю, что @Will дает лучший ответ здесь http://stackoverflow.com/a/501165/39532 – mezoid

+2

Будьте осторожны, потому что 'Convert.ToInt32' и' Decimal.ToInt32' ведут себя по-другому. Из MSDN: 'Decimal.ToInt32' - возвращаемое значение является неотъемлемой частью десятичного значения; дробные цифры ** усекаются **. 'Convert.ToInt32' - Возвращаемое значение ** округлено ** до ближайшего 32-разрядного целого числа со знаком. Если значение находится на полпути между двумя целыми числами, возвращается четное число; то есть 4.5 преобразуется в 4, а 5.5 преобразуется в 6. – vezucci

8

System.Decimal осуществляет интерфейс IConvertable, который имеет элемент ToInt32().

Работает ли у вас System.Decimal.ToInt32()?

+1

Из [документации] (https://msdn.microsoft.com/en-us/library/bb350799 (v = vs.110) .aspx) : «Этот API поддерживает инфраструктуру .NET Framework и не предназначен для непосредственного использования из вашего кода». Почему бы не использовать Convert.ToInt32? –

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

Это должно работать нормально.

+0

Осторожно, с явной информацией о конверсиях может быть потеряна. – Phaedrus

+18

При переходе от десятичной к int информация почти всегда будет потеряна, но я считаю, что это своего рода точка. – Dinah

38
int i = (int)d; 

предоставит вам номер, закругленный.

Если вы хотите, чтобы округлить до ближайшего четного числа (т.е.> 0,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" . Это может быть хорошо, но вы должны быть откровенно об этом и сделать явное приведение, чтобы показать, что вы можете потерять информацию.

8

Утонченный трюк для быстрого округления - это добавить .5 перед тем, как придать десятичную цифру в int.

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? – Badaro

+0

В то время я был довольно знаком с C#, и по какой-то причине я не осознавал, что эти функции существуют. Это на самом деле трюк, который я изучил на C/C++, где это было очевидно более полезно. – DeadlyBrad42

+1

Что делать, если десятичное значение было, например, -9,3? – supercat

64

Вы не можете.

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

Это означает, что если вы разделите десятичное число, большее, чем int.MaxValue, вы переполнитесь, и если десятичная метка будет меньше, чем int.MinValue, она будет опущена.

Что происходит, когда вы находитесь под/переполнением? Одна из двух вещей. Если ваша сборка не установлена ​​(т. Е. CLR не заботится о том, если вы это сделаете), ваше приложение будет продолжено после значения over/underflows, но значение в int будет не таким, как вы ожидали. Это может привести к прерывистым ошибкам и может быть трудно исправить. Вы закончите свое приложение в неизвестном состоянии, что может привести к тому, что ваше приложение разложит все важные данные, над которыми он работает. Нехорошо.

Если ваша сборка проверена (свойства-> сборка-> расширенная-> проверка арифметического переполнения/недостаточного потока или опция/checked компилятора), ваш код генерирует исключение, когда происходит переполнение/переполнение. Это, вероятно, лучше, чем нет; однако по умолчанию для сборок не нужно проверять наличие переполнения/недогрузки.

Реальный вопрос: «Что вы пытаетесь сделать?» Не зная своих требований, никто не может сказать вам, что вы должны делать в этом случае, кроме очевидного: НЕ ДЕЛАЙТЕ ЭТО.

Если вам конкретно неинтересно, ответы здесь действительны. Тем не менее, вы должны общаться ваше понимание того, что переполнение может произойти, и что это не имеет значения, обернув код произнесения в бесконтрольно блок

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

То, что, как люди, приезжающие за вас понимаю, вы не и если в будущем кто-то изменяет ваши сборки на/checked, ваш код не будет неожиданно ломаться.

Если все, что вы хотите сделать, это отбросить дробную часть номера, оставив неотъемлемую часть, вы можете использовать Math.Truncate.

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

Хотя я подозреваю, что это то же самое, что и под капотом, если ввод является десятичным, я чувствую себя более комфортно с помощью Decimal.Truncate, чем Math.Truncate, так как последний также принимает удвоения и, следовательно, можно понять, что он способен усекать даже числа, которые не являются основанием 10, в отличие от Decimal.Truncate, который является истинным усечением базового номера 10. – Brian

+6

Непроверенные контексты не применяются к десятичным знакам; операции над десятичными знаками будут вызывать OverflowExceptions независимо. – Dave

+0

@ dave Черт, ты прав. BRB, ECMA. – Will

6

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

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

checked { 
    int i = (int)Math.Floor(d); 
} 
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 Unboxing conversions

+2

Добавляем больше к нему для справки: это потому, что вы можете удалить только те же оригиналы. Здесь 'SELECT SCOPE_IDENTITY()' возвращает 'числовой (38, 0)', который переводит на 'decimal' .NET. 'foo.ExecuteScalar()' возвращает 'decimal' в виде" object ", который нельзя передать непосредственно в' int'. '(int) (десятичный) foo.ExecuteScalar()' или 'Convert.ToInt32 (foo.ExecuteScalar())' будет работать. – rageit

5

десятичной d = 5.5;

int i = decimal.ToInt32(d);// you will get i = 5 

исх: link text

3

Округление десятичных чисел до ближайшего целого числа

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

, когда a = 49.9, то b = 50

, когда a = 49.5, то b = 50

когда a = 49.4, затем b = 49 т.д.

Смежные вопросы