Суббота, 18.05.2024, 11:35 | Приветствую Вас Гость | Регистрация | Вход

Форум трейдеров рынка Forex

Присоединяйтесь к сообществу форекс трейдеров прямо сейчас!
Научитесь зарабатывать и приумножать деньги
Расскажите о своем опыте торговли
Получите ответы на любые вопросы от специалистов
Знакомьтесь и общайтесь с лидерами рынка
Читайте актуальную и закрытую информацию и многое другое...

InstaForex

Функции перевода чисел между десятичной и двоичной системами - Сообщество успешных трейдеров

[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 1 из 1
  • 1
Сообщество успешных трейдеров » Программное обеспечение » Программирование на MQL » Функции перевода чисел между десятичной и двоичной системами
Функции перевода чисел между десятичной и двоичной системами
tagДата: Суббота, 17.11.2012, 02:58 | Сообщение # 1
Главный администратор
Группа: Управляющие
Сообщений: 1490
Репутация: 0
Статус: Offline
Недавно писал скрипт для заказчика, и мне понадобилась функция перевода двоичных данных в десятичные. Сначала я попробовал решить эту задачу "в лоб":
Code
int BinToInt(string s) {
    int i;
    int res = 0;
    int l = StringLen(s);
    for (i = 0; i < l; i++)
      if (StringGetChar(s, i) == '1')
        res += MathPow(2, l - i - 1);
    return(res);
}

Коротко опишу приведенный код. На входе мы получаем двоичное число в виде строки, состоящей из нолей и единиц. В переменную l мы получаем длину этой строки и пробегаемся по ней в цикле с итератором i, сверяя каждый раз i-тую позицию строки, является ли она единицей. Если является, то к результирующей переменной res, изначально проинициализированной нолем, мы прибавляем число, равное 2 в степени позиции в двоичном числе, отсчитанной с ноля, начиная справа. Поскольку позиция в строке и позиция в двоичном числе не совпадает, мы вычисляем ее через длину строки: l - i - 1. После выполнения цикла возвращаем результат res.

Вроде работает и хорошо. Но потом мне понадобилась обратная функция для перевода из десятичного числа в двоичное. Решение "в лоб" на этот раз мне показалось несколько громоздким и я задумался над оптимизацией алгоритма. Вспоминал институтский курс численных методов, но убедившись, что он был забыт мной начисто, нашел такой алгоритм в гугле
Code

string IntToBin(int i) {
    string s;
    if (i == 0) return("0");
    while (i > 0) {
      s = StringConcatenate(i % 2, s);
      i = i / 2;
    }
    return(s);
}

Здесь используется тот факт, что при умножении двоичного числа на 2 происходит сдвиг влево всех его битов и, соответственно, наоборот, при делении - сдвиг вправо. В остатке получаем значение текущего (крайнего правого) бита. В самом начале мы делаем проверку на 0. В случае если входное число равно нолю, то функция вернет пустую строку, вместо этого мы возвращаем строку "0" и прерываем выполнение функции. Далее в цикле while мы выполняем следующие действия: к результирющей сроке s добавляем слева бит, полученный в остатке от целочисленного деления на 2, и входное число i делим на 2. Деление целочисленное, поскольку тип переменной целочисленный. Цикл продолжается до тех пор, пока в результате деления мы не получим 0.

Алгоритм довольно изящный, но мало того, он еще и более быстродействующий, нежели решение "в лоб". Я задумался, что, наверное, и первую функцию неплохо было бы переписать с использованием умножения на 2. И мучила мысль, а будет ли существенный выигрыш? Стоит ли? Учитывая то, что данные функции мне потребовались для скрипта, в котором будет производиться работа с достатчоно большими массивами данных, а сами функции будут вызываться в огромных циклах, время выполнения может играть ощутимую роль.

Прежде всего я реализовал этот "изящный" алгоритм для перевода из десятичного числа в двоичное:
Code
int BinToInt2(string s) {
    int i;
    int res = 0;
    int l = StringLen(s);
    for (i = 0; i < l; i++) {
      res *= 2;
      if (StringGetChar(s, i) == '1')
        res += 1;
    }
    return(res);
}

Суть его, я думаю, понятна. Разница только в цикле, где я сразу умножаю результирующую переменную на 2, для осуществления сдвига, а потом извлекаю очередной бит из строки. Если этот бит равен единице, то прибавляем эту единицу к результату.

Как же убедиться в том, каким будет выигрыш во времени и будет ли он вообще? Для этих целей обычно используется профилирование, но в MQL4 нет никаких встроенных средств для осуществления этой процедуры. Я решил воспользоваться старым проверенным методом больших циклов. Для осуществления профилирования функций я написал следующий "стендовый" скрипт:
Code
//+------------------------------------------------------------------+
//|                    bvnprofile.mq4 |
//|                    bvn |
//|                    http://junkabyss.com |
//|                    Version 0.1.0        |
//+------------------------------------------------------------------+
#property copyright "bvn"
#property link      "junkabyss.com"
#property show_inputs

extern int    CycleCount = 10000000;
//+------------------------------------------------------------------+
//| script program start function                    |
//+------------------------------------------------------------------+
int start() {
    datetime before, after;
    int full;
    int i;
//----

    // source data
    string v = "11001010011100";

    // get time before
    before = TimeLocal();

    // profiling
    for (i = 0; i < CycleCount; i++) {
      // call function here
      BinToInt(v);
    }

    // get time after
    after = TimeLocal();
    full = after - before;
      
    // out results
    Comment(StringConcatenate("Time before: ", before, " Time after: ", after, " Full time: ", full));
//----
    return(0);
}

Здесь в цикле из 10 млн итераций происходят многократные вызовы указанной функции. Время в секундах до и после выполнения цикла засекается. После чего делаются подсчет времени и вывод результата. Количество итераций я вынес в параметр скрипта, чтобы можно было подобрать подходящее. Рекомендуется задавать сразу небольшое количество, а потом аккуратно постепенно увеличивать его, иначе, переборщив, можно "подвесить" весь терминал.

В итоге получил следующие результаты. При использовании исходного решения в лоб: 13 секунд, а при использовании "изящного" алгоритма: 10 секунд.

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

Будем благодарны, если Вы поделитесь этим материалом в социальных сетях:



Рейтинг дилинговых центров и брокеров Forex / Форекс.
www.forex-rating.at.ua
 
Сообщество успешных трейдеров » Программное обеспечение » Программирование на MQL » Функции перевода чисел между десятичной и двоичной системами
  • Страница 1 из 1
  • 1
Поиск:

Полезные ресурсы

Рейтинг дилинговых центров и брокеров Forex / Форекс. О рынке Forex. Словарь трейдера. Инструменты Forex. Видеоуроки Forex. Аналитика
www.forex-rating.at.ua


Обобщенный форекс-прогноз на каждый день
www.rating-forex.at.ua


Отзывы о брокерах рынка Forex
www.ratingfx.at.ua


Стратегии Forex
www.fxstrategy.at.ua


Бизнес форум о заработке в интернете
www.netbiz.at.ua


Топ 5 управляющих ПАММ
www.forex-online.at.ua


Индикаторы Forex
www.forex-archive.at.ua


Советник ILAN 1.6 Dynamic. Зарабатывает 1000 долларов за месяц
www.my1job.narod.ru



Поиск

Реклама