Удваивать.Попробуйте проанализировать или преобразовать.В Double - что быстрее и безопаснее?
Вопрос
Мое приложение считывает файл Excel с помощью VSTO и добавляет прочитанные данные в StringDictionary
.Он добавляет только те данные, которые представляют собой числа с несколькими цифрами (1000 1000,2 1000,34 - запятая является разделителем в российских стандартах).
Что лучше, чтобы проверить, является ли текущая строка соответствующим номером?
object data, string key; // data had read
try
{
Convert.ToDouble(regionData, CultureInfo.CurrentCulture);
dic.Add(key, regionData.ToString());
}
catch (InvalidCastException)
{
// is not a number
}
или
double d;
string str = data.ToString();
if (Double.TryParse(str, out d)) // if done, then is a number
{
dic.Add(key, str);
}
Я должен использовать StringDictionary
вместо того , чтобы Dictionary<string, double>
из-за следующих проблем с алгоритмом синтаксического анализа.
Мои вопросы:Какой способ быстрее?Что безопаснее?
И не лучше ли позвонить Convert.ToDouble(object)
или Convert.ToDouble(string)
?
Решение
Я провел быстрый ненаучный тест в режиме выпуска.Я использовал два входа:"2.34523" и "badinput" были введены в оба метода и повторены 1 000 000 раз.
Допустимый ввод:
Double.TryParse = 646ms
Convert.ToDouble = 662 ms
Не сильно отличается, как и ожидалось.По сути, для корректных входных данных это одно и то же.
Неверный ввод:
Double.TryParse = 612ms
Convert.ToDouble = ..
Что ж..это продолжалось долгое время.Я перезапускаю все это, используя 1000 итераций, и Convert.ToDouble
с плохим вводом заняло 8,3 секунды.Если подсчитать в среднем, то это заняло бы более 2 часов.Меня не волнует, насколько прост тест, в случае недопустимого ввода, Convert.ToDouble
увеличение числа исключений испортит вашу производительность.
Итак, вот еще один голос за TryParse
с некоторыми цифрами в подтверждение этого.
Другие советы
Для начала я бы использовал double.Parse
вместо того , чтобы Convert.ToDouble
в первую очередь.
Относительно того, следует ли вам использовать Parse
или TryParse
:можете ли вы продолжить, если есть неверные входные данные, или это действительно исключительное условие?Если это исключительный случай, используйте Parse
и пусть это взорвется, если входные данные будут плохими.Если это ожидаемо и может быть аккуратно обработано, используйте TryParse
.
Рекомендации по проектированию .NET Framework рекомендуют использовать методы Try.Избегать исключений обычно является хорошей идеей.
Convert.ToDouble(object)
будет делать ((IConvertible) object).ToDouble(null);
Который вызовет Convert.ToDouble(string, null)
Так что быстрее вызвать строковую версию.
Однако строковая версия просто делает это:
if (value == null)
{
return 0.0;
}
return double.Parse(value, NumberStyles.Float | NumberStyles.AllowThousands, provider);
Так что быстрее делать double.Parse
напрямую.
Если вы не собираетесь обрабатывать исключение, используйте TryParse .TryParse работает быстрее, потому что ему не нужно обрабатывать всю трассировку стека исключений.
Обычно я стараюсь избегать Convert
класс (значение:Я им не пользуюсь) потому что я нахожу это очень запутанным:код дает слишком мало подсказок о том, что именно здесь происходит, поскольку Convert
позволяет выполнять множество семантически очень разных преобразований с одним и тем же кодом.Это затрудняет программисту контроль за тем, что именно происходит.
Поэтому мой совет - никогда не использовать этот класс.На самом деле в этом тоже нет необходимости (за исключением двоичного форматирования числа, потому что обычный ToString
метод числовых классов не предлагает подходящего метода для этого).
Если вы не уверены на 100% в своих входных данных, что случается редко, вам следует использовать Double.Попробуйте проанализировать.
Convert.ToDouble will throw an exception on non-numbers
Double.Parse will throw an exception on non-numbers or null
Double.TryParse will return false or 0 on any of the above without generating an exception.
Скорость синтаксического анализа становится второстепенной, когда вы создаете исключение, потому что оно не намного медленнее исключения.
Здесь много ненависти к классу Convert...Просто чтобы немного сбалансировать, у Convert есть одно преимущество - если вам вручают объект,
Convert.ToDouble(o);
может просто легко вернуть значение, если o уже является Double (или int, или что-либо легко кастуируемое).
Используя Double.Синтаксический анализ или Double.TryParse отлично подходит, если у вас уже есть это в строке, но
Double.Parse(o.ToString());
должен уйти сделать строка, подлежащая анализу в первую очередь и зависящая от вашего ввода, которая может быть более дорогой.
Дважды.Попробуйте проанализировать IMO.
Вам будет легче с этим справиться, вы будете точно знать, где произошла ошибка.
Затем вы можете поступить с ним так, как считаете нужным, если он возвращает false (т. е. не удалось преобразовать).
Я всегда предпочитал использовать TryParse()
методы, потому что это вернет успех или неудачу преобразования, не беспокоясь об исключениях.
Лично я нахожу, что TryParse
метод проще для чтения, какой из них вы на самом деле захотите использовать, зависит от вашего варианта использования:если ошибки могут быть обработаны локально, вы ожидаете ошибок и bool от TryParse
это хорошо, иначе вы могли бы просто позволить исключениям работать.
Я бы ожидал, что TryParse
к тому же быть быстрее, поскольку это позволяет избежать накладных расходов на обработку исключений.Но используйте эталонный инструмент, например Мини-верстак Джона Скита чтобы сравнить различные возможности.
Это интересный старый вопрос.Я добавляю ответ, потому что никто не заметил пару моментов в исходном вопросе.
Что быстрее:Преобразовать.Удвоить или удвоить.Попробуйте проанализировать?Что безопаснее:Преобразовать.Удвоить или удвоить.Попробуйте проанализировать?
Я собираюсь ответить на оба эти вопроса (я обновлю ответ позже), подробно, но сначала:
Для безопасности, вещь каждый программист пропустил в этом вопросе строку (курсив мой):
Он добавляет только те данные, которые представляют собой числа с несколькими цифрами (1000 1000,2 1000,34 - запятая - это разделитель в российских стандартах).
Далее следует этот пример кода:
Convert.ToDouble(regionData, CultureInfo.CurrentCulture);
Что здесь интересно, так это то, что если электронные таблицы представлены в русском числовом формате, но Excel неправильно ввел поля ячеек, какова правильная интерпретация значений, поступающих из Excel?
Вот еще одна интересная вещь в этих двух примерах, касающаяся скорости:
catch (InvalidCastException)
{
// is not a number
}
Скорее всего, это приведет к созданию MSIL, который выглядит следующим образом:
catch [mscorlib]System.InvalidCastException
{
IL_0023: stloc.0
IL_0024: nop
IL_0025: ldloc.0
IL_0026: nop
IL_002b: nop
IL_002c: nop
IL_002d: leave.s IL_002f
} // end handler
IL_002f: nop
IL_0030: return
В этом смысле мы, вероятно, можем сравнить общее количество инструкций MSIL, выполняемых каждой программой - подробнее об этом позже, когда я обновлю этот пост.
Я считаю, что код должен быть правильным, понятным и быстрым... В таком порядке!