Лучший (самый безопасный) способ конвертировать из двойного в int

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

14
задан Joel B 23 August 2010 в 15:41
поделиться

8 ответов

Я думаю, что вам лучше всего сделать следующее:

checked
{
    try
    {
        int bar = (int)foo;
    }
    catch (OverflowException)
    {
     ...          
    }
}

Из Таблицы явных числовых преобразований

При преобразовании из двойного или плавающего значения в целочисленный тип, значение усекается. Если полученное интегральное значение выходит за пределы диапазон целевого значения, результат зависит от переполнения проверка контекста. В проверенном контексте возникает исключение OverflowException. брошено, а в непроверенном контексте результатом является неуказанный значение типа назначения.

Примечание. Вариант 2 также вызывает OverflowException, когда это необходимо.

27
ответ дан 1 December 2019 в 06:12
поделиться

Я предпочитаю вариант 2.

Для подтверждения того, что все получилось, нужно проверить исключения, так же, как вы проверяете 'parsed' в варианте 1:

try
{
    bar = Convert.ToInt32(foo); 
}
catch(OverflowException)
{
    // no can do!
{

Если вы преобразовывали строку и т.д. вместо двойки, вы можете получить 'FormatException'.

Edit

Изначально я сказал, что вариант 2 не лучше варианта 1, на что @0xA3 указал, что это неверно. Вариант 1 хуже, потому что он конвертирует в строку перед разбором в целое число, что означает, что он менее эффективен. Вы также не получите OverflowException, если double выходит за пределы целочисленного диапазона (что вам может быть нужно, а может и не быть) - хотя 'parsed' в этом случае будет False.

6
ответ дан 1 December 2019 в 06:12
поделиться

Вариант 3a, не использующий исключения, всегда возвращает значение:

    Int32 Convert(Double d)
    {
        if (d <= (double)Int32.MinValue)
            return Int32.MinValue;
        else if (d >= (double)Int32.MaxValue)
            return Int32.MaxValue;
        else 
            return (Int32)d;
    }
4
ответ дан 1 December 2019 в 06:12
поделиться

Я всегда использую класс Convert, он мне очень элегантен, удобен, и вы можете перехватывать определенные исключения, определенные в VS intellisense.

3
ответ дан 1 December 2019 в 06:12
поделиться

Опции (1) и (2) делают, по сути, одно и то же. Вариант (1) дает вам блок if (разобранный) , тогда как вариант (2) выдает ошибку для любого double , который не может быть представлен как int .

Вариант (3) по сути такой же, как вариант (2), за исключением того, что он имеет дополнительную проверку MinValue / MaxValue , которой нет у других.

В итоге: эти три части кода делают разные вещи. Вариант (3) выглядит наиболее надежным, поскольку в нем есть дополнительная проверка диапазона.

Правка: Если подумать, воспользуйтесь уловкой @Ani checked - вы получите проверку диапазона бесплатно.

2
ответ дан 1 December 2019 в 06:12
поделиться

Я понимаю, что это не совсем то, о чем просил OP, но эта информация может оказаться полезной.

Вот сравнение (из http://www.dotnetspider.com/resources/1812-Difference-among-Int-Parse-Convert-ToInt.aspx )

        string s1 = "1234";
        string s2 = "1234.65";
        string s3 = null;
        string s4 = "12345678901234567890123456789012345678901234567890";

        int result;
        bool success;

        result = Int32.Parse(s1);      // 1234
        result = Int32.Parse(s2);      // FormatException
        result = Int32.Parse(s3);      // ArgumentNullException
        result = Int32.Parse(s4);      // OverflowException

        result = Convert.ToInt32(s1);      // 1234
        result = Convert.ToInt32(s2);      // FormatException
        result = Convert.ToInt32(s3);      // 0
        result = Convert.ToInt32(s4);      // OverflowException

        success = Int32.TryParse(s1, out result);      // 1234
        success = Int32.TryParse(s2, out result);      // 0
        success = Int32.TryParse(s3, out result);      // 0
        success = Int32.TryParse(s4, out result);      // 0
5
ответ дан 1 December 2019 в 06:12
поделиться

Я бы использовал второй вариант. Коротко, чисто, и все работает.

Вы также можете изучить класс BigInteger в .Net4, и вам не придется проверять переполнение.

double foo = 1;            
BigInteger bigint = new BigInteger(foo);
3
ответ дан 1 December 2019 в 06:12
поделиться

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

int ToInt(double foo)
{
    int result = (int)foo;
    if (foo != result)
        throw new ArgumentException()

    return result;
}

Это позволит избежать недопустимых преобразований. Если можно округлить до ближайшего целого числа, используйте Math.Round и проверьте, находится ли результат в пределах 0,5. Это гарантирует, что ваш метод не получит NaN или бесконечности.

2
ответ дан 1 December 2019 в 06:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: