Использование переменных.
В программировании имеются два часто используемых понятия это объявление переменной и ее инициализация.
Что такое объявление переменной?
Это декларация переменной в форме [идентификатор имяПеременной;], где символ ";" (точка с запятой) означает оператор завершения выражения
- Код: выделить все
//примеры объявлений переменных
int i;
bool b;
string s;
double d;
color col;
datetime date;
Что такое инициализация?
Это присвоение переменной первоначального значения. В вышеприведенном примере переменным значения не присваиваются, однако при компиляции программы компилятор автоматически всем переменным присвоит начальные значения, такое присвоение значений компилятором имеет название присвоение значений по умолчанию.
Соответственно, всем переменным будут присвоены следующие значения
- Код: выделить все
//примеры инициализации переменных
i = 0;
b = false;
s = "";
d = 0.0;
col = CRL_NONE; // отсутствие цвета, т.е. это цвет фона окна с графиком
date = 0; //соответствует, 01.01.1970 0:00
Далее поговорим об основных манипуляциях с переменными.
1. выражения - это изменения значений переменных (инициализации, арифметические операции и т.п.), запись выражений заканчивается оператором ";"
например,
- Код: выделить все
a = 1;
b = (a + 1) / 3;
2. арифметические операции
тут все просто,
- Код: выделить все
x = x + y; // увеличение числа на y или такой вариант записи x += x;
x = x - y; // уменьшение числа на y или такой вариант записи x -= x;
x = x * y; // увеличение числа в y раз или такой вариант записи x *= x;
x = x / y; // уменьшение числа в y раз или такой вариант записи x /= x;
для деления стоит уточнить такой момент, что если производится деление целых чисел (тип int), то производится округление до целых чисел путем отбрасывания дробной части, например,
- Код: выделить все
int a = 18;
int b = 10;
int c = 3;
double e = a / b * c;
Возникает вопрос каким будет результат ?
Если посчитать, то вроде как должно получиться 5.4, но с учетом того, что переменные имеют тип int, то результат будет 3. Чтобы математика была "правильной" нужно использовать тип double, по крайней мере один из участников деления должен иметь тип double. Суть в том, что когда числа делятся будучи int типом получается 1.8 и после округления имеем 1, а далее понятен результат.
Бывает, что программа так устроена, что типы нельзя поменять, т.е. значения в данном случае переменных a, b и c возвращаются какими-то функциями и их переделка проблематична. В таком случае можно сделать ход конем и добавить лишний множитель, который позволит выполнить правильный расчет
- Код: выделить все
double e = [b]1.0[/b] * a / b * c;
кроме четырех основных операций есть еще получение остатка от деления для этого используют оператор %, а выглядит это так
- Код: выделить все
a = 5 % 2; // имеем результат 1
данная операция производится только над целыми числами (int)
инкрементация и декрементация, т.е. увеличение/уменьшение значения на единицу
- Код: выделить все
i++;// эквивалентно i = i + 1;
i--;// эквивалентно i = i - 1;
3. Операции отношения
- Код: выделить все
Истина, если a равно b a == b;
Истина, если a не равно b a != b;
Истина, если a меньше b a < b;
Истина, если a больше b a > b;
Истина, если a меньше или равно b a <= b;
Истина, если a больше или равно b a >= b;
4. Логические операции
логическое отрицание (
!) применимо
только к булевым переменным
- Код: выделить все
bool a = true;
bool b = !a; // false
логическое или (
||) возвращает истину если хотя бы одно из условий истина, в противном случае возвращает ложь
- Код: выделить все
int a = 4;
bool b = false;
if (a > 5 || !b){
Print("истина");
}
логическая операция и (
&&) возвращает истину только в случае, если все условия в выражении истина
- Код: выделить все
int a = 4;
bool b = false;
if (a >= 3 && !b){
Print("истина");
}
Ну и пару слов о переменных используемых в качестве параметров функции и видимости переменных в коде.
Как уже писалось ранее внешние (extern) и глобальные (те, что объявляются вне функций) переменные доступны из любого места в программе.
Возможные казусы программирования:Имена переменных глобальной в внутренней (по отношению к функции) одинаковы к чему это может привести ?
- Код: выделить все
int period = 10; // глобальная переменная
int start(){
int a = get();
Print(a);
}
int get(){
int period = 0; // локальная переменная
return(period * 3);
}
Зачастую при больших объемах кода ненарочно внутри функций создаются одноименные глобальным переменные.
Хотя по смыслу подразумевалось использование именно глобальных, что приводит к возможным ошибкам. Или например, такое чаще бывает, когда пишешь сначала тестовую функцию, а потом некоторые внутренние параметры функции выносишь в глобальные переменные и случайно забываешь удалить локальные. И вроде рассчитываешь что должны использоваться уже глобальные и смотришь на результат, а он совсем не тот, хотя ошибки явной нет.
Более интересен другой пример
- Код: выделить все
int period = 10; // глобальная переменная
int start(){
int a = get(period);//тут передается значение 10
Print(a);//возвращено значение 30
Ptint(period);// <---------------------- а здесь все равно 10 ?!
}
int get(int period){//пришло 10
period *= 3;//увеличили
return(period);//вернули 30
}
Нередко бывает такая конструкция, что в функцию передается параметр (глобальная переменная), а в самой функции имя параметра совпадает с именем глобальной переменной и тут возникают логические казусы, т.к. разработчик ожидает, что переменная должна измениться и при принте переменной period в функции start() имеет не изменившееся значение. И такая ситуация зачастую становится непонятной в силу того, что в разных языках такие вещи обрабатываются по разному.
В данном случае в функции get() входной параметр - int period, является локальной переменной для самой функции, и поэтому чтобы мы не делали с ней внутри функции, то все это и останется внутри нее. А правильнее говорить, что параметр в функцию передается по значению, что означает, что в функцию передается копия исходного значения, что в свою очередь подразумевает, что эта копия хранится в другой "ячейке" памяти нежели оригинал, и естественно, ее изменение не может никак влиять на оригинал, с которого эта копия взята.
На тот случай, если нужно чтобы в место вызова, в данном случае это функция start(), возвращалось измененное значение передаваемого в функцию параметра, то значение в функцию нужно передавать по ссылке, что означает передачу оригинальной ссылки на "ячейку" памяти, т.е. все изменения внутри функции будут сохранены. Чтобы передавать значение по ссылке нужно в объявлении переменной period в функции get() добавить символ амперсанта.
- Код: выделить все
int get(int[b]&[/b] period){
period *= 3;
return(period);
}
Понятие необязательных переменных.
В функциях могут быть необязательные параметры, которые можно не передавать. Например, для работы с ценами очень часто (почти всегда) следут использовать нормализацию цен. О чем тут речь? Цена любого инструмента имеет фиксированное число знаков после запятой, и если мы каким-либо образом вычисляли цену, а иногда даже беря текущую цену, получали лишние знаки, то такую цену - ненормализованную, т.е. не приведенную к правильному значению знаков после зяпятой нельзя использовать для торговых операций, т.к. бeдет выдана ошибка.
Так вот, для нормализации значений есть функция NormalizeDouble(), которая имеет два параметра - значение, которое нужно нормализовать и количество знаков, до которых нужно произвести нормализацию. На основе этой функции можно слделать свою функцию специально для нормализации цен.
- Код: выделить все
double N(double value, int digits=Digits){
return(NormalizeDouble(value, digits));
}
Обратите внимание на то, как задан второй параметр int digits=Digits что означает эта запись ?
Во-первых Digits - это системная константа, которая выдает количество значков после запятой для текущего инструмента, т.е. тот инструмент, на котором исполняется код во-вторых, запись int digits=Digits, говорит о том, что этот параметр необязателен, что это значит ?
Это значит, что можно вызывать эту функцию как со вторым параметром, так и без него, при этом если функция вызывается без параметра, то внутри функции переменная digits инициализируется значением по умолчанию, которое равно Digits.
Возьмем для примера инструмент EURUSD на "четырехначной" платформе у него четыре знака после зяпятой, таким образом имеем
- Код: выделить все
double price = 1.33333333333333;
double n = N(price, 8); // нормализуем до восьми знаков после запятой, т.е. имеем 1.33333333
double n = N(price); // нормализуем до Digits знаков после запятой, т.е. до 4-х знаков, имеем 1.3333