Оператор NormalizeDouble работает с ошибками? - страница 2

 
dokpiknik писал(а) >>

К сожалению, я установил то же самое. Выходит ошибка происходит во время сравнения дробных (double) нормализованных ("усечённых") чисел. Таким образом, остаётся одно: дробные числа превращать в целые (разделив их на Point) и равнивать уже их между собой. Уж в этом-то случае (при сравнении целых чисел) должно быть всё тип-топ! Или та же проблема с +0/-0 может возникнуть? Однако, всё это достаточно неудобно...

Тоже может быть проблема с +-0. Перед заталкиванием значения в инт надо делать MathRound(), тогда будет правильно работать.

 
dokpiknik >>:

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

Вновь и вновь я делал тщательную проверку алгоритма и не находил ошибок. Мистика! Только тогда я поставил под сомнение правильность отработки указанного оператора и заменил его простой функцией:

MathRound(number/Point)*Point, где number - ненормализованная цена.

Ошибочные сообщения как рукой сняло! Что бы это значило?

Три возможные причины:

1. Машинное представление чисел в блоке расчетов с числами с плавающей точкой. (представление как бесконечная дробь)

2. Метод округления, принятый для операций в сопроцессоре. (их несколько типов)

3. Алгоритм округления в самой функции NormalizeDouble. (мне неизвестен)

Говорить о некорректности выполнения функции нельзя, пока неизвестно точно подробности о всех трёх причинах.

 
dokpiknik >>:

Полностью согласен с Вами. Между тем, думаю, что алгоритм сравнения в системных программах может быть усовершенствован. Уверен в этом. Microsoft, например, не позволяет себе подобной неряшливости. Да, никто это долго и терпеть не стал бы.

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

Особенно повеселил выделенный фрагмент - видите ли и МТ и винда написана на одном и том же языке. И все базовые возможности одинаковы. 

Теме этой оч много времени. Поднималась неоднократно. И, кстати, местами и НормалайзДабл работает некорректно - но это следствие машинного способа хранения данных, а не языковой реализации.

В вашем случае корректным будет сравнивать разницу значений, например, с величиной, равной 0.5*Point.

Примерно так : 

if(op[i] != op_obj) - НЕВЕРНО

if( MathAbs(op[i]-op_obj) >0.5*Point ) - ВЕРНО

Успехов и учите матчасть ;)....

ЗЫ хотел проехаться по поводу некорректных высказываний - потом передумал. Прежде всего ищите то, что Вы не допонимаете - а не устраивайте "гон" на разработчиков. 

 

Функция действительно не так работает, сегодня потратил на это целый день

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

void ModifyOrder(double pp=-1, double sl=0, double tp=0, datetime ex=0) {
  bool   fm;
  color  cl;
  double op, pa, pb, os, ot;
  int    dg=MarketInfo(OrderSymbol(), MODE_DIGITS), er, it;

  if (pp<=0) pp=OrderOpenPrice();
  if (sl<0 ) sl=OrderStopLoss();
  if (tp<0 ) tp=OrderTakeProfit();
  
  pp=NormalizeDouble(pp, dg);
  sl=NormalizeDouble(sl, dg);
  tp=NormalizeDouble(tp, dg);
  op=NormalizeDouble(OrderOpenPrice() , dg);
  os=NormalizeDouble(OrderStopLoss()  , dg);
  ot=NormalizeDouble(OrderTakeProfit(), dg);

  if (pp!=op || sl!=os || tp!=ot) {
    for (it=1; it<=NumberOfTry; it++) {
      if (!IsTesting() && (!IsExpertEnabled() || IsStopped())) break;
      while (!IsTradeAllowed()) Sleep(5000);
      RefreshRates();
      fm=OrderModify(OrderTicket(), pp, sl, tp, ex, cl);
      if (fm) {
        if (UseSound) PlaySound(NameFileSound); break;
      } else {
        er=GetLastError();
        pa=MarketInfo(OrderSymbol(), MODE_ASK);
        pb=MarketInfo(OrderSymbol(), MODE_BID);
        Print("Error(",er,") modifying order: ",ErrorDescription(er),", try ",it);
        Print("Ask=",pa,"  Bid=",pb,"  sy=",OrderSymbol(),
              "  op="+GetNameOP(OrderType()),"  pp=",pp,"  sl=",sl,"  tp=",tp);
        Sleep(1000*10);
      }
    }
  }
}

заменил её полностью на просто

OrderModify(OrderTicket()....

все заработало,


Также при установки ордеров, использовал для их цены функцию NormalizeDouble ( )

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

Заменил на вариант автора ветки

ppB = MathRound((Ask + aB)/Point)*Point;
всё заработало без ошибок
 
HideYourRichess писал(а) >>

Три возможные причины:

1. Машинное представление чисел в блоке расчетов с числами с плавающей точкой. (представление как бесконечная дробь)

2. Метод округления, принятый для операций в сопроцессоре. (их несколько типов)

3. Алгоритм округления в самой функции NormalizeDouble. (мне неизвестен)

Говорить о некорректности выполнения функции нельзя, пока неизвестно точно подробности о всех трёх причинах.

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

Ещё раз повторю - ни один приличный язык программирования не позволяет себе подобной неряшливости.

 
dokpiknik писал(а) >>

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

Ещё раз повторю - ни один приличный язык программирования не позволяет себе подобной неряшливости.

Откройте MetaEditor. В навигаторе во вкладке файлы найдите ветку libraries, откройте файл stdlib.mq4. Найдите функцию CompareDoubles.

Дело не в языках программирования, а в способе представления вещественных чисел в платформе Intel.

Мы, как разработчики, не вправе ничего "улучшать" без ведома пользователей. Представьте ситуацию, когда программист сравнивает вещественные числа с точностью до 300-го знака после запятой, а мы ему в ответ: "числа равны". А?

Зачем чего-то пробовать искать? Почитайте наши статьи. Напустите на форум поиск по слову "сравнение вещественных чисел". Посмотрите наши примеры (хотя бы stdlib).

PS. Назовите хотя бы один "приличный язык программирования, который не позволяет себе подобной неряшливости" на платформе Intel?

 
VladislavVG писал(а) >>

Особенно повеселил выделенный фрагмент - видите ли и МТ и винда написана на одном и том же языке. И все базовые возможности одинаковы.

Теме этой оч много времени. Поднималась неоднократно. И, кстати, местами и НормалайзДабл работает некорректно - но это следствие машинного способа хранения данных, а не языковой реализации.

В вашем случае корректным будет сравнивать разницу значений, например, с величиной, равной 0.5*Point.

Примерно так :

if(op[i] != op_obj) - НЕВЕРНО

if( MathAbs(op[i]-op_obj) >0.5*Point ) - ВЕРНО

Успехов и учите матчасть ;)....

ЗЫ хотел проехаться по поводу некорректных высказываний - потом передумал. Прежде всего ищите то, что Вы не допонимаете - а не устраивайте "гон" на разработчиков.

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

Дискуссия же на форуме может помочь разработчикам улучшить свой товар. Нормальный предприниматель критику воспринимает как большое благо. Так что о "гоне на разработчиков" с моей стороны не может быть и речи. А вот всеобщий "одобрямс", который до сих пор имеется в России и мешает ей достойно развиваться, на Западе как-то не в чести.

И последнее. Учусь я всегда охотно, даже если мне об этом не напоминают.

 
dokpiknik >>:

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

Ещё раз повторю - ни один приличный язык программирования не позволяет себе подобной неряшливости.

Большая ошибка. Эти "неряшливости" характерны всем языкам программирования. Почему, смотри пункт 1. Зависит от процессора.

Тут скорее "неряшливость" программиста, если он не знает таких вещей.

 
satop писал(а) >>

Функция действительно не так работает, сегодня потратил на это целый день

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

заменил её полностью на просто

все заработало,

Также при установки ордеров, использовал для их цены функцию NormalizeDouble ( )

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

Заменил на вариант автора ветки

всё заработало без ошибок

Большое спасибо за подмогу.

 
stringo писал(а) >>

Откройте MetaEditor. В навигаторе во вкладке файлы найдите ветку libraries, откройте файл stdlib.mq4. Найдите функцию CompareDoubles.

Дело не в языках программирования, а в способе представления вещественных чисел в платформе Intel.

Мы, как разработчики, не вправе ничего "улучшать" без ведома пользователей. Представьте ситуацию, когда программист сравнивает вещественные числа с точностью до 300-го знака после запятой, а мы ему в ответ: "числа равны". А?

Зачем чего-то пробовать искать? Почитайте наши статьи. Напустите на форум поиск по слову "сравнение вещественных чисел". Посмотрите наши примеры (хотя бы stdlib).

PS. Назовите хотя бы один "приличный язык программирования, который не позволяет себе подобной неряшливости" на платформе Intel?

Спасибо, посмотрю.

Причина обращения: