Длинные котировки или числа не поддающиеся нормализации.

 
Есть индикатор, он производит сравнение котировок между собой и на основании этого строит линию, по одной из подходящих цен. Изначально последовательность действий была такая:
//RT - rates total
//PC - prevev calculated
{
   RT = iBars(_Symbol, InTimeframe);
   Index = RT - PC - 1;
   if(Index == -1)
      Index = 0;
   
   for(Index = Index; Index > -1; Index--)
   {
      OHLCCorrector();
      LimitZone();
   }   
   PC = RT;
   return(rates_total)
}
и индикатор исправно работал.

Затем я научил его строить Фибоначчи, но для оптимизации рисования потребовалось определять появление нового бара и код стал таким:
{
   RT = iBars(_Symbol, InTimeframe);
   Index = RT - PC - 1;
   if(Index == -1)
      Index = 0;
   
   for(Index = Index; Index > -1; Index--)
   {
      OHLCCorrector();
      LimitZone();
      if((RT - PC) == 1)
         Fibonacci();
      PC = RT - Index;
   }
   return(rates_total);
}
этот код отказался исправно работать, основная линия индикатора обрывалась. При пошаговом изучении происходящего обнаружилось, что теперь ни одно из условий для записи определённого значения в индикаторный буфер не выполнялось. Причиной стала котировка несоответствующей точности. То есть вместо 0,8386  iClose выдавал 0,838599999999. Такие же длинные котировки проскакивают и при печати в журнал. Я попробовал применить нормализацию. Нормализация до 3-х знаков сработала, но до 4-х никак не помогла. Я попробовал преобразование Double - Str - Double с точностью 4, но и это не принесло результата. В архиве котировок, если туда вручную заглянуть, таких длинных котировок нет.
 
http://www.softelectro.ru/ieee754.html -  хорошая статья, прочитайте про точность представления вещественных чисел
 

Тут только поможет нормализация. Переменные должны быть типа float. С типом double у меня тоже не всегда нормализовало. А вот с флоатом никаих проблем не возникало.

 
Не используйте float!
Этот тип позволяет хранить только очень приблизительные значения.

Пример:
input double d=10.0;
input float  f=10.0f;

void OnStart()
  {
   Print(typename(d),": ",(7/d)*1000.0);
   Print(typename(f),": ",(7/f)*1000.0);
  }

Результат:
float:  699.9998688697815
double: 700.0
 

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

а переменные типа дабл не всегда правильно нормализуются 

 
ksili:

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

а переменные типа дабл не всегда правильно нормализуются 

Числа нормализуются до нужного знака всегда!

Но вот не всегда вещественное число можно представить в виде конечной двоичной записи и погрешность для float выше, т.к. мантиса значительно меньше(23 бита), чем у double (52 бита).
 
ksili:

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

а переменные типа дабл не всегда правильно нормализуются 

Вы сначала прочитайте статью, которую Вам порекомендовали.

Топикстартер же даже не подозревает, что 0,838599999999 является нормализованным значением и в дальнейшей нормализации не нуждается. Тоже не читал документацию https://docs.mql4.com/ru/basis/types/double, https://docs.mql4.com/ru/convert/normalizedouble, https://docs.mql4.com/ru/basis/operations/relation

 
ksili:

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

а переменные типа дабл не всегда правильно нормализуются 

Если вас интересует равенство двух вещественных чисел, то знания о нормализации являются излишеством.

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

 
mql5:
http://www.softelectro.ru/ieee754.html -  хорошая статья, прочитайте про точность представления вещественных чисел

А почему бы вам не ввести (в MQL), автоматическую нормализацию всех расчетов?

Можно по указанию при инициализации: 

— по разрядности текущего инструмента, 

— по выбранной разрядности

— при явном указании (иначе по инструменту)

— без нормализцации (как сейчас) 

... 

 

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

 
noloxe:

А почему бы вам не ввести (в MQL), автоматическую нормализацию всех расчетов?

Можно по указанию при инициализации: 

— по разрядности текущего инструмента, 

— по выбранной разрядности

— при явном указании (иначе по инструменту)

— без нормализцации (как сейчас) 

... 

 

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


Здесь говорится, что сейчас расчеты идут без нормализации. Это не так. Вне всяких языков уровня MQL само аппаратное представление чисел с плавающей точкой на разных платформах (Стандарт IEEE 754-1985) уже включает такие понятия:

  • как представлять нормализованные положительные и отрицательные числа с плавающей точкой
  • как представлять денормализованные положительные и отрицательные числа с плавающей точкой
  • как представлять нулевые числа
  • как представлять специальную величину бесконечность (Infinity)
  • как представлять специальную величину "Не число" (NaN или NaNs)
  • четыре режима округления

  • Чуть выше mql5 дал ссылку http://www.softelectro.ru/ieee754.html, где это написано. намного подробнее

    Понятие "нормализации вещественных чисел" в MQL отвечает очень специальной задаче, сводится к десятичному округлению до 0-8 значащих цифр и, конечно же, противоречит общепринятому понятию нормализованности вещественных чисел в двоичном представлении. Его лучше не развивать, а назвать иначе. Зачем ему дали название из общеупотребительных, не знаю, но, по-моему, хорошо бы избавиться от возникающих неясностей. Простой путь - число типа "Цена" с теми же свойствами.

    P.S. В своих опусах я использую еще число типа "Объем". Указываю в начале программы единицы измерения объема (0.01 или 0.001 лота, это и минимальный объем, и шаг объемов) и остальные операции с объемами свожу к целым числам (в MT5 так не выходит).

    P.P.S. Думается, в https://docs.mql4.com/ru/basis/operations/relation фразу "Для корректного сравнения двух вещественных чисел необходимо сравнивать нормализованную разницу этих чисел с нулевым значением." необходимо поправить или убрать. Если править, то заменить "двух вещественных чисел" на "двух вещественных чисел ценовой природы (курс, уровень ордера...) "

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