Который является быстрым сравнением: Преобразовать. ToInt32(stringValue) == intValue или stringValue == intValue. ToString ()

При разработке моего приложения я столкнулся с некоторым материалом сравнения, здесь было это:

    string str = "12345";
    int j = 12345;
    if (str == j.ToString())
    {
        //do my logic
    }

Я думал, что вышеупомянутый материал может также быть, покончите:

    string str = "12345";
    int j = 12345;
    if (Convert.ToInt32(str) == j)
    {
        //do my logic
    }

Таким образом, я разработал пример кода для тестирования с точки зрения производительности, какой лучше

        var iterationCount = 1000000;
        var watch = new Stopwatch();
        watch.Start();
        string str = "12345";
        int j = 12345;
        for (var i = 0; i < iterationCount; i++)
        {
            if (str == j.ToString())
            {
                //do my logic
            }
        }
        watch.Stop();

И второй:

  var iterationCount = 1000000;
    var watch = new Stopwatch();
    watch.Start();
    string str = "12345";
    int j = 12345;
    for (var i = 0; i < iterationCount; i++)
    {
        if (Convert.ToInt32(str) == j)
        {
            //do my logic
        }
    }
    watch.Stop();

При выполнении вышеупомянутых двух тестов я нашел, что вышеупомянутые тесты давали почти то же истекшее время. Я хотел бы обсудить, какой является лучшим подходом? И есть ли какой-либо другой подход лучше, чем два выше два?

12
задан Raghav 16 December 2009 в 20:26
поделиться

8 ответов

Ваш тест в корне ошибочен. Компилятор и среда выполнения - действительно умные звери, которые оптимизируют код как во время компиляции, так и во время выполнения (JIT-ing). В этом случае вы делаете одно и то же каждый раз , что будет обнаружено компилятором и оптимизировано, поэтому время будет одинаковым для каждого метода.

Попробуйте эту версию (у меня только .Net 2.0, отсюда и небольшие изменения):

using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;

namespace ToStringTest
{
    class Program
    {
        const int
            iterationCount = 1000000;

        static TimeSpan Test1()
        {
            Stopwatch watch = new Stopwatch();
            watch.Start();
            string str = "12345";
            int j = 12345;
            for (int i = 0; i < iterationCount; i++)
            {
                if (str == i.ToString())
                {
                    //do my logic
                }
            }
            watch.Stop();
            return watch.Elapsed;
        }

        static TimeSpan Test2()
        {
            Stopwatch watch = new Stopwatch();
            watch.Start();
            string str = "12345";
            int j = 12345;
            for (int i = 0; i < iterationCount; i++)
            {
                if (Convert.ToInt32(i) == j)
                {
                    //do my logic
                }
            }
            watch.Stop();
            return watch.Elapsed;
        }

        static void Main(string[] args)
        {
            Console.WriteLine("ToString = " + Test1().TotalMilliseconds);
            Console.WriteLine("Convert = " + Test2().TotalMilliseconds);
        }
    }
}

, и вы увидите огромную разницу. Один на два порядка быстрее другого. И действительно очевидно, какая именно.

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

Для преобразования строки в int требуется следующее:

total = 0
for each character in string
  total = total * 10 + value of charater

и ToString требует:

string = ""
while value != 0
  string.AddToFront value % 10
  value /= 10

Умножение намного проще и быстрее для процессора, чем деление. Учитывая выбор алгоритма с большим количеством умножений по сравнению с алгоритмом с большим количеством делений, всегда выбирайте первый, так как он всегда будет быстрее.

Затем есть сравнение, сравнение int - int просто, загрузите каждое значение в зарегистрируйте и сравните - пара машинных инструкций и готово. Сравнение двух строк требует тестирования каждого символа в строках по одному - в приведенном вами примере это было 5 байтов (int, вероятно, 4 байта), что означает больше обращений к памяти.

Сравнение двух строк требует тестирования каждого символа в строках по одному - в приведенном вами примере это было 5 байтов (int, вероятно, 4 байта), что означает больше обращений к памяти.

Сравнение двух строк требует тестирования каждого символа в строках по одному - в приведенном вами примере это было 5 байтов (int, вероятно, 4 байта), что означает больше обращений к памяти.

16
ответ дан 2 December 2019 в 03:32
поделиться

Что ж - производительность не должна быть единственным, что имеет значение.

Вы должны спросить, хотите ли вы сравнить фактическое значение или только представление числа.

Возьмем следующее пример: «00001» равно 1? Если вы хотите преобразовать строку в int, используя комбинацию Int.TryParse, а затем сравнить их.

Могут быть и другие различия в зависимости от локальных настроек. Возможно, пользователь установил формат чисел, например, «1,000,000» - если вы сравните эту строку с 1000000.ToString (), результат будет ложным.

13
ответ дан 2 December 2019 в 03:32
поделиться

Я предпочитаю i.ToString () == str , поскольку ничто не гарантирует, что Convert.ToInt32 (str) не выйдет из строя.

6
ответ дан 2 December 2019 в 03:32
поделиться

Ура, вы показываете, что логика вашего домена находится внутри цикла профилирования, поэтому вы не проверяли разницу во времени между версиями Convert и ToString вашего кода; вы тестировали общее время преобразования плюс выполнение вашей бизнес-логики. Если ваша бизнес-логика медленная и определяет время преобразования, конечно, вы увидите одно и то же время в каждой версии.

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

Теперь, что касается того, какую версию использовать: вам нужно начать с указания именно того, что вы ' повторное тестирование. Что вы вкладываете? "007" когда-нибудь будет входом? «007» отличается от целого числа 7? Будет ли когда-нибудь входом «1024»? Есть ли проблемы с локализацией?

3
ответ дан 2 December 2019 в 03:32
поделиться

Если производительность почти такая же, выберите версию, которая более читабельна.

Лично я считаю, что подход .ToString () проще для понимания и менее подвержен возможным проблемам приведения типов, чем другой подход.

2
ответ дан 2 December 2019 в 03:32
поделиться

Семантика немного отличается. "01" == 1.ToString () равно false , 1 == Convert.ToInt32 ("01") равно true .

Если синтаксический анализ может пойти не так (строка не является допустимым числом), тогда Int32.TryParse быстрее, чем использовать Convert.ToInt32 () .

.
2
ответ дан 2 December 2019 в 03:32
поделиться

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

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

0
ответ дан 2 December 2019 в 03:32
поделиться

Хорошо, я продвигаюсь на один шаг вперед и тестирую следующим образом:

    int j = 123;
    for (var i = 0; i < iterationCount; i++)
    {
        j.ToString();
    }

второй: string str = "123";

        for (var i = 0; i < iterationCount; i++)
        {
            Convert.ToInt32(str);
        }

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

0
ответ дан 2 December 2019 в 03:32
поделиться
Другие вопросы по тегам:

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