Было бы полезно узнать, хотите ли вы округлить до ближайшего целого числа или просто отбросить числа после десятичной дроби (то есть: всегда округлять)
Дина
128
я, честно говоря, не вижу смысла в опровержении подлинных вопросов. да, ответ можно найти в Google, но разве это не улучшит качество сайта, если люди перестанут закрывать каждый второй вопрос? не то, чтобы этот вопрос был спамом или чем-то еще, и я уверен, что это будет полезно для многих
новичков
Ответы:
268
Используйте Convert.ToInt32из , mscorlibкак в
decimalvalue=3.14m;int n =Convert.ToInt32(value);
Смотрите MSDN . Вы также можете использовать Decimal.ToInt32. Опять же, смотрите MSDN . Наконец, вы можете сделать прямой бросок, как в
decimalvalue=3.14m;int n =(int)value;
который использует явный оператор приведения. Смотрите MSDN .
Остерегайтесь: Конверт имеет некоторое удивительное поведение для определенного преобразования (по nullсравнению 0с ""). Я бы рекомендовал никогда не использовать Convert, если вам абсолютно не нужна его гибкость (то есть в динамически типизированных сценариях)
Имон Нербонн
1
-1, так как это не будет работать для таких значений, как decimal.MaxValue и decimal.MinValue и приводит к OverflowException. Я считаю, что @Will дает лучший ответ здесь stackoverflow.com/a/501165/39532
мезоид
8
Будьте осторожны, потому что Convert.ToInt32и Decimal.ToInt32ведите себя по-другому. Из MSDN: Decimal.ToInt32- возвращаемое значение является неотъемлемой частью десятичного значения; дробные цифры усекаются . Convert.ToInt32- Возвращаемое значение округляется до ближайшего 32-разрядного целого числа со знаком. Если значение находится посередине между двумя целыми числами, возвращается четное число; то есть 4,5 преобразуется в 4, а 5,5 преобразуется в 6.
Везуччи
67
Ты не можешь
Ну, конечно, вы могли бы , однако int (System.Int32) недостаточно велик, чтобы содержать все возможные десятичные значения.
Это означает, что если вы приведете десятичное число, которое больше, чем int.MaxValue, вы переполнитесь, а если десятичное число будет меньше, чем int.MinValue, оно опустится.
Что происходит, когда вы находитесь под / переполнение? Одна из двух вещей. Если ваша сборка не проверена (т. Е. CLR не волнует, если вы это сделаете), ваше приложение продолжит работу после того, как значение превысит / понизит значение, но значение в int будет не тем, что вы ожидали. Это может привести к периодическим ошибкам и может быть трудно исправить. В конечном итоге ваше приложение окажется в неизвестном состоянии, что может привести к повреждению вашего приложения какими-либо важными данными, над которыми он работает. Не хорошо.
Если ваша сборка проверена (свойства-> build-> advanced-> проверка на арифметическое переполнение / недополнение или параметр / checked компилятора), ваш код сгенерирует исключение при возникновении недостаточного / переполнения. Это, вероятно, лучше, чем нет; однако по умолчанию для сборок не выполняется проверка на переполнение / переполнение.
Настоящий вопрос - «что ты пытаешься сделать?» Не зная ваших требований, никто не может сказать вам, что вы должны делать в этом случае, кроме очевидного: НЕ ДЕЛАЙТЕ ЭТОГО.
Если вам не все равно, ответы здесь действительны. Тем не менее, вы должны сообщить о своем понимании того, что может произойти переполнение и что это не имеет значения, оборачивая ваш приведенный код в непроверенный блок
unchecked{// do your conversions that may underflow/overflow here}
Таким образом, люди, идущие за вами, понимают, что вам все равно, и если в будущем кто-то изменит ваши сборки на / флажок, ваш код не будет неожиданно сломан.
Если все, что вы хотите сделать, это отбросить дробную часть числа, оставив неотъемлемую часть, вы можете использовать Math.Truncate.
decimal actual =10.5M;decimal expected =10M;Assert.AreEqual(expected,Math.Truncate(actual));
Хотя я подозреваю, что они одинаковы, если ввод десятичный, мне удобнее использовать 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". Это может быть хорошо, но вы должны четко заявить об этом и сделать явное приведение, чтобы показать, что вы можете потерять информацию.
Вы на самом деле хотите, чтобы MidpointRounding.AwayFromZero, если вы хотите, чтобы> * .5 всегда округлялся, основываясь на моем опыте опробования приведенного выше кода, при просмотре примера вывода здесь: msdn.microsoft.com/en-us/library/…
Элайджа Лофгрен
@ElijahLofgren Это отчасти зависит: если вы делаете статистику, ToEvenследует предотвратить смещение статистики. Однако если вы работаете с платными предметами или деньгами, это AwayFromZeroкажется правильным выбором.
Из документации : «Этот API поддерживает инфраструктуру .NET Framework и не предназначен для использования непосредственно из вашего кода». Почему бы не использовать Convert.ToInt32?
Х. Уолпер
7
Аккуратный трюк для быстрого округления состоит в том, чтобы добавить .5, прежде чем вы приведете десятичное число к int.
Зачем делать это, когда есть Math.Floor и Math.Ceiling?
Badaro
В то время я был довольно новичком в C # и по какой-то причине я не осознавал, что эти функции существуют. Это на самом деле трюк, который я узнал из C / C ++, где он был, очевидно, более полезным.
DeadlyBrad42
1
Что если десятичное значение было, например, -9,3?
Обратите внимание, что все они также возвращают Decimal - поскольку Decimal имеет больший диапазон значений, чем Int32, поэтому вам все равно придется приводить (и проверять наличие переполнения / потери значения).
Я считаю, что оператор приведения не работает, если у вас есть десятичное число в штучной упаковке (то есть десятичное значение внутри типа объекта). Convert.ToInt32 (десятичный как объект) прекрасно работает в этом случае.
Эта ситуация возникает при получении значений IDENTITY / AUTONUMBER из базы данных:
SqlCommand foo =newSqlCommand("INSERT INTO...; SELECT SCOPE_IDENTITY()", conn);int ID =Convert.ToInt32(foo.ExecuteScalar());// worksint ID =(int)foo.ExecuteScalar();// throws InvalidCastException
Добавим больше к нему для справки: это потому, что вы можете распаковать только тот же тип оригинала. Здесь 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.
Ответы:
Используйте
Convert.ToInt32
из ,mscorlib
как вСмотрите MSDN . Вы также можете использовать
Decimal.ToInt32
. Опять же, смотрите MSDN . Наконец, вы можете сделать прямой бросок, как вкоторый использует явный оператор приведения. Смотрите MSDN .
источник
null
сравнению0
с""
). Я бы рекомендовал никогда не использовать Convert, если вам абсолютно не нужна его гибкость (то есть в динамически типизированных сценариях)OverflowException
. Я считаю, что @Will дает лучший ответ здесь stackoverflow.com/a/501165/39532Convert.ToInt32
иDecimal.ToInt32
ведите себя по-другому. Из MSDN:Decimal.ToInt32
- возвращаемое значение является неотъемлемой частью десятичного значения; дробные цифры усекаются .Convert.ToInt32
- Возвращаемое значение округляется до ближайшего 32-разрядного целого числа со знаком. Если значение находится посередине между двумя целыми числами, возвращается четное число; то есть 4,5 преобразуется в 4, а 5,5 преобразуется в 6.Ты не можешь
Ну, конечно, вы могли бы , однако int (System.Int32) недостаточно велик, чтобы содержать все возможные десятичные значения.
Это означает, что если вы приведете десятичное число, которое больше, чем int.MaxValue, вы переполнитесь, а если десятичное число будет меньше, чем int.MinValue, оно опустится.
Что происходит, когда вы находитесь под / переполнение? Одна из двух вещей. Если ваша сборка не проверена (т. Е. CLR не волнует, если вы это сделаете), ваше приложение продолжит работу после того, как значение превысит / понизит значение, но значение в int будет не тем, что вы ожидали. Это может привести к периодическим ошибкам и может быть трудно исправить. В конечном итоге ваше приложение окажется в неизвестном состоянии, что может привести к повреждению вашего приложения какими-либо важными данными, над которыми он работает. Не хорошо.
Если ваша сборка проверена (свойства-> build-> advanced-> проверка на арифметическое переполнение / недополнение или параметр / checked компилятора), ваш код сгенерирует исключение при возникновении недостаточного / переполнения. Это, вероятно, лучше, чем нет; однако по умолчанию для сборок не выполняется проверка на переполнение / переполнение.
Настоящий вопрос - «что ты пытаешься сделать?» Не зная ваших требований, никто не может сказать вам, что вы должны делать в этом случае, кроме очевидного: НЕ ДЕЛАЙТЕ ЭТОГО.
Если вам не все равно, ответы здесь действительны. Тем не менее, вы должны сообщить о своем понимании того, что может произойти переполнение и что это не имеет значения, оборачивая ваш приведенный код в непроверенный блок
Таким образом, люди, идущие за вами, понимают, что вам все равно, и если в будущем кто-то изменит ваши сборки на / флажок, ваш код не будет неожиданно сломан.
Если все, что вы хотите сделать, это отбросить дробную часть числа, оставив неотъемлемую часть, вы можете использовать Math.Truncate.
источник
даст вам число, округленное в меньшую сторону.
Если вы хотите округлить до ближайшего четного числа (т.е.> .5 округлится вверх), вы можете использовать
В общем, вы можете привести между всеми числовыми типами в C #. Если нет информации, которая будет потеряна во время приведения, вы можете сделать это неявно:
хотя вы можете сделать это явно, если хотите:
Тем не менее, если вы собираетесь потерять информацию через актерский состав, вы должны сделать это явно (чтобы показать, что вы знаете, что вы можете потерять информацию):
Здесь вы теряете ".5". Это может быть хорошо, но вы должны четко заявить об этом и сделать явное приведение, чтобы показать, что вы можете потерять информацию.
источник
ToEven
следует предотвратить смещение статистики. Однако если вы работаете с платными предметами или деньгами, этоAwayFromZero
кажется правильным выбором.Это должно работать просто отлично.
источник
Вот очень удобная конвертируемая страница типа данных для других. http://www.convertdatatypes.com/Convert-decimal-to-int-in-CSharp.html
источник
System.Decimal
реализуетIConvertable
интерфейс, который имеетToInt32()
член.Звонок
System.Decimal.ToInt32()
работает для вас?источник
Аккуратный трюк для быстрого округления состоит в том, чтобы добавить .5, прежде чем вы приведете десятичное число к int.
Еще уходит
i=10
, ноСобрался бы так, что
i=11
.источник
Я предпочитаю использовать Math.Round , Math.Floor , Math.Ceiling или Math.Truncate чтобы явно установить режим округления в зависимости от ситуации.
Обратите внимание, что все они также возвращают Decimal - поскольку Decimal имеет больший диапазон значений, чем Int32, поэтому вам все равно придется приводить (и проверять наличие переполнения / потери значения).
источник
десятичный
d = 5.5
;ссылка: текст ссылки
источник
Округление десятичной дроби до ближайшего целого
когда
a = 49.9
тогдаb = 50
когда
a = 49.5
тогдаb = 50
когда
a = 49.4
, тоb = 49
и т. д.источник
Я считаю, что оператор приведения не работает, если у вас есть десятичное число в штучной упаковке (то есть десятичное значение внутри типа объекта). Convert.ToInt32 (десятичный как объект) прекрасно работает в этом случае.
Эта ситуация возникает при получении значений IDENTITY / AUTONUMBER из базы данных:
См. 4.3.2 Распаковка конверсий
источник
SELECT SCOPE_IDENTITY()
возвращает,numeric(38, 0)
что переводит наdecimal
.NET.foo.ExecuteScalar()
возвращает вdecimal
штучной упаковке,object
который не может быть приведен непосредственно кint
.(int)(decimal)foo.ExecuteScalar()
илиConvert.ToInt32(foo.ExecuteScalar())
будет работать.Кажется, что ни один ответ не имеет отношения к OverflowException / UnderflowException, возникающему при попытке преобразовать десятичное число, выходящее за пределы диапазона int.
Это решение вернет максимальное или минимальное возможное значение типа int, если десятичное значение находится вне диапазона int. Возможно, вы захотите добавить некоторые округления с Math.Round, Math.Ceiling или Math.Floor для случаев, когда значение находится внутри диапазона int.
источник