Ошибки, баги, вопросы - страница 107

 
Yedelkin:
simpleton, я тоже пошёл по аналогичному пути, но использовал явное приведение к типу int. Исходил из того, что максимально возможный размер лота будет ограничен либо брокером/дилером, либо размером собственных средств. В связи с чем должно вполне хватить использования int . Как Вы полагаете, имеются ли при таком подходе (округление "снизу" с помощью int) какие-нибудь подводные камни?

Для реальной торговли, скорее всего, - да, достаточно int/uint.

Но если в тестере гонять, то для некоторых экспериментов может и не хватить.

Никаких подводных камней, кроме возможных очередных глюков реализации MQL5, при использовании int нет, если прогарантировать попадание того целого N из формулы в диапазон 0..INT_MAX и, тем самым, прогарантировать отсутствие переполнения. То есть, заменить проверку

tmp < ULONG_MAX * stepvol

на

tmp < INT_MAX * stepvol

Вообще-то тип int - знаковый, половина его возможных значений лежит в области отрицательных чисел, а здесь всегда будут неотрицательные. Нерационально использовать int, когда имеется беззнаковый uint, имеющий тот же размер, но вдвое больший диапазон в области неотрицательных чисел. Поэтому, уж если останавливаться на int/uint, то лучше выбрать uint и заменить проверку, соответственно, на:

tmp < UINT_MAX * stepvol
 

gumgum:

#property script_show_inputs

Спасибо за подсказку.
 
simpleton:

Для реальной торговли, скорее всего, - да, достаточно int/uint.

..Вообще-то тип int - знаковый, половина его возможных значений лежит в области отрицательных чисел, а здесь всегда будут неотрицательные. Нерационально использовать int, когда имеется беззнаковый uint, имеющий тот же размер, но вдвое больший диапазон в области неотрицательных чисел. Поэтому, уж если останавливаться на int/uint, то лучше выбрать uint и заменить проверку, соответственно, на:

Да, всё понял, спасибо!
 

Это не баг но интересное наблюдение предупреждение касательно типов

Как Вы думаете сколько будет дважды два , т.е. 2*2

думаете 4  возможно Вы правы!

ну хорошо, а так
двести тысяч на двести тысяч

200000 * 200000

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

40000000000.

А теперь простенький код на языке машины

long lots = 200000*200000;

заметьте, что тип принимающей значение переменной long т.е.
Минимальное значение -9 223 372 036 854 775 808, максимальное значение 9 223 372 036 854 775 807.

Распечатываем итог и получаем

lots = 1345294336
это далеко не дважды два и будет вам два.

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

тоесть правильно надо так

long lots = (long) 200000 * (long) 200000;

как вариант, можно еще через вспомогательные переменные.

Документация по MQL5: Основы языка / Типы данных / Приведение типов
Документация по MQL5: Основы языка / Типы данных / Приведение типов
  • www.mql5.com
Основы языка / Типы данных / Приведение типов - Документация по MQL5
 

Дальше больше.

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

 Вот код

long A = AccountInfoInteger(ACCOUNT_LOGIN);  // 661701
long B = A;
long C = 661701;
Print(" A=",A,"  B=",B,"  C=",C);
long X =10000;

long L1 = A*X;
long L2 = B*X;
long L3 = C*X;

Print(" L1=",L1,"   L2=",L2,"   L3=",L3);

А вот результат

L1=2322042704   L2=2322042704   L3=6617010000
A =661701        B =661701      C =661701
исходные данные одни, а результат разный
Файлы:
servis.mq5  2 kb
 

SHOOTER777:

А теперь простенький код на языке машины

long lots = 200000*200000;

заметьте, что тип принимающей значение переменной long т.е.
Минимальное значение -9 223 372 036 854 775 808, максимальное значение 9 223 372 036 854 775 807.

Распечатываем итог и получаем

lots = 1345294336
это далеко не дважды два и будет вам два.

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

тоесть правильно надо так

long lots = (long) 200000 * (long) 200000;

как вариант, можно еще через вспомогательные переменные.

"Обычные числа" - это константные выражения, которые тоже имеют тип. В данном случае - тип int.

Выражение, состоящее из умножения двух подвыражений, каждое типа int, - тоже имеет тип int. Вот тут-то и происходит переполнение.

И только потом, при инициализации переменной типа long происходит неявное приведение от типа выражения int к типу long.

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

 
SHOOTER777:

Дальше больше.

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

 Вот код

А вот результат

исходные данные одни, а результат разный

Похоже, перепутан лог и код. Приведённый код работает "чисто". А, чтобы получить такой лог, пришлось переменные A и B сделать типа int или uint, а переменную X - типа uint:

void OnStart()
{
int A = 661701;
int B = A;
long C = 661701;
Print(" A=",A,"  B=",B,"  C=",C);
uint X =10000;

long L1 = A*X;
long L2 = B*X;
long L3 = C*X;

Print(" L1=",L1,"   L2=",L2,"   L3=",L3);
}

/* Вывод в лог (хронология - сверху вниз):
KO      0       1 (EURUSD,M15)  00:46:28         A=661701  B=661701  C=661701
OE      0       1 (EURUSD,M15)  00:46:28         L1=2322042704   L2=2322042704   L3=6617010000
*/

А вот - работа оригинального кода:

void OnStart()
{
long A = 661701;
long B = A;
long C = 661701;
Print(" A=",A,"  B=",B,"  C=",C);
long X =10000;

long L1 = A*X;
long L2 = B*X;
long L3 = C*X;

Print(" L1=",L1,"   L2=",L2,"   L3=",L3);
}

/* Вывод в лог (хронология сверху вниз):
DL      0       1 (EURUSD,M15)  00:49:13         A=661701  B=661701  C=661701
HG      0       1 (EURUSD,M15)  00:49:13         L1=6617010000   L2=6617010000   L3=6617010000
*/

Build 314 (20 Aug 2010).

Документация по MQL5: Основы языка / Типы данных / Целые типы / Типы char, short, int и long
Документация по MQL5: Основы языка / Типы данных / Целые типы / Типы char, short, int и long
  • www.mql5.com
Основы языка / Типы данных / Целые типы / Типы char, short, int и long - Документация по MQL5
 

Подскажите, вот нужно например получить значение какого-то индикатора. Раньше я получал его совершенно точно и гарантированно используя встроенную функцию. Теперь я должен ее написать сам используя кучу кода, буферы хендлы и т.п. Но! Не в это дело. Главное для меня в том, что код становится глючным буквально в каждой строчке, так как нужно эту каждую строчку кода проверять не получилась ли ошибка... И вобще я думал, что все эти навороты, классы и то что было элементарно а стало громоздко и неудобно сделали для увеличения скорости, надежности и т.п... Читаю статью про 20 сигналов... там написано:

"Нельзя обратиться к данным индикатора сразу после его создания, так как на расчет значений индикатора требуется некоторое время, и поэтому создавать хэндлы индикаторов лучше всего в OnInit()."

Далее на каждую строчку идут проверки

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

 

Т. е. вместо быстродействия я должен что, делать цикл(сколько раз?) по этой функции, что-бы в конце концов получить результат... А если мне нужны отдельные значения отдельных линий разных индикаторов периодически... Это на каждое значение отдельную функцию... Это же сколько лишних переменных и кода...

Короче поясните, ссылку дайте, я хочу понять смысл всего этого, почему так, а не как надежнее...

И хорошо бы ответы на такие вопросы поместить в раздел переход с мкл4 на мкл5 справки, или на форуме создать соответствующий раздел без обсуждения, конкретно вопрос-ответ, причем с пояснением почему так... например очень доступно объяснено здесь про период, вот в таком же плане хотелось бы иметь ответы на элементарные вопросы

 
Dmitriy2:

Подскажите, вот нужно например получить значение какого-то индикатора. Раньше я получал его совершенно точно и гарантированно используя встроенную функцию. Теперь я должен ее написать сам используя кучу кода, буферы хендлы и т.п. Но! Не в это дело. Главное для меня в том, что код становится глючным буквально в каждой строчке, так как нужно эту каждую строчку кода проверять не получилась ли ошибка... И вобще я думал, что все эти навороты, классы и то что было элементарно а стало громоздко и неудобно сделали для увеличения скорости, надежности и т.п... Читаю статью про 20 сигналов... там написано:

"Нельзя обратиться к данным индикатора сразу после его создания, так как на расчет значений индикатора требуется некоторое время, и поэтому создавать хэндлы индикаторов лучше всего в OnInit()."

Далее на каждую строчку идут проверки

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

 

Т. е. вместо быстродействия я должен что, делать цикл(сколько раз?) по этой функции, что-бы в конце концов получить результат... А если мне нужны отдельные значения отдельных линий разных индикаторов периодически... Это на каждое значение отдельную функцию... Это же сколько лишних переменных и кода...

Короче поясните, ссылку дайте, я хочу понять смысл всего этого, почему так, а не как надежнее...

И хорошо бы ответы на такие вопросы поместить в раздел переход с мкл4 на мкл5 справки, или на форуме создать соответствующий раздел без обсуждения, конкретно вопрос-ответ, причем с пояснением почему так... например очень доступно объяснено здесь про период, вот в таком же плане хотелось бы иметь ответы на элементарные вопросы

 

Надежней? Почему получать хэндлы при инициализации это не надежно? Почему проверять наличие необходимых данных это не надежно? И тем более, почему наличие проверок это не надежно?

Для новичков может не так просто, но со временем все станет понятным...

 
Interesting:

Надежней? Почему получать хэндлы при инициализации это не надежно? Почему проверять наличие необходимых данных это не надежно? И тем более, почему наличие проверок это не надежно?

Для новичков может не так просто, но со временем все станет понятным...

  Как автор данной статьи полностью поддерживаю вас. проверка данных не ухудшает скорости работы программы в целом, может только на 0.01 %, я такую проверку не делал, а то что данные нужно проверить перед их использованием это как раз для стабильности всей системы в целом, иначе могут быть непредсказуемые последствия вполть до вылета терминала в целом.
Причина обращения: