Самый простой способ посчитать количество знаков после запятой? - страница 5

 
igrok333:

для 0.01 не работает

лучше так:

а так намного быстрее:

int Digits2(double x) { // для 0<x<1
   int N=0;
   while((int)x==0) {
      N++;
      x*=10;
   }
   return N;
}
 
Nikolai Semko:

а так намного быстрее:

А как проверить скорость выполнения программы, в наносекундах?
 
Igor Makanu:

изучайте https://www.mql5.com/ru/forum/287618

там все есть

себе взял этот https://www.mql5.com/ru/forum/287618/page13#comment_9797522

для определения количества знаков после запятой для нормализации объёма ордера (лот) работает без проблем

Почему нельзя просто так:

#define DIGS_MAX 8

void OnStart()
{
  double dv = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);

  int digs = 0;
  for(; digs <= DIGS_MAX && NormalizeDouble(dv, digs) != dv; ++digs);

  if(digs <= DIGS_MAX) Print(dv, " ", digs);
  else Print(dv, " is wrong number"); // если digs > DIGS_MAX, то dv не подходит для NormalizeDouble()
}
 
Вроде, люди все неглупые, а повелись. Количество десятичных знаков (точность) не определяют, а задают. 
 
Алексей Тарабанов:
Вроде, люди все неглупые, а повелись. Количество десятичных знаков (точность) не определяют, а задают. 

это да, но если такое число 5,3560000000000000000000003 

тут интересны лишь первые три знака после запятой.

 
Aleksey Nikolayev:

Почему нельзя просто так:

можно

по моей ссылке весь топик об этих тренировках для ума ))

ЗЫ: разработчики писали, что NormalizeDouble() дорогая по вычислениям функция, если использовать в оптимизации часто, тогда лучше уйти от ее использования

 
Igor Makanu:

можно

по моей ссылке весь топик об этих тренировках для ума ))

ЗЫ: разработчики писали, что NormalizeDouble() дорогая по вычислениям функция, если использовать в оптимизации часто, тогда лучше уйти от ее использования

Вроде бы, число знаков для нормализации объёма считается только один раз - при инициализации советника.

При торговле, использование NormalizeDouble() считаю неизбежным, ибо совсем не готов заменять её некими своими поделками)

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

 
Igor Makanu:

можно

по моей ссылке весь топик об этих тренировках для ума ))

ЗЫ: разработчики писали, что NormalizeDouble() дорогая по вычислениям функция, если использовать в оптимизации часто, тогда лучше уйти от ее использования

умножаю на 10 в степени нужного количества знаков, беру целую часть (а это не тип целый) и делю обратно. Не помогает только, если такого дабл без хвоста нет в двоичном варианте. Но тут не победить, да и нужды нет.

 
Aleksey Nikolayev:

Вроде бы, число знаков для нормализации объёма считается только один раз - при инициализации советника.

При торговле, использование NormalizeDouble() считаю неизбежным, ибо совсем не готов заменять её некими своими поделками)

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

Нормализация нужна только перед торговыми действиями, они нежные на эту тему, и для удобства просмотра напечатанного) 

В расчетах не делаю.

 
Aleksey Nikolayev:

Для оптимизации же - надо смотреть будет ли существенный выигрыш от подобной замены.

Мне NormalizeDouble() показалась вполне оптимизированной (по времени исполнения). Заполнение массива ненормализованными числами, естественно, быстрее чем нормализованными, но если добавить деление на число, то штатная нормализация уже быстрее. Так что, пока не вижу смысла в конструировании своих велосипедов для ускорения оптимизации.

Возможно, ошибся в расчётах, посему привожу использованный скрипт:

void OnStart()
{
  double step = 1e-4;
  int digs = 4, nstep = 1e6;
  double v, vn[], t0, t1, dt1, dt2;
  ArrayResize(vn, nstep);
  // без нормализации
  t0 = (double)GetMicrosecondCount();
  for(int i = 1; i <= nstep; ++i)
  {
    v = step * i;
    vn[i - 1] = v ; // немного быстрее чем NormalizeDouble()
    //vn[i - 1] = v / step; // немного медленнее чем NormalizeDouble()
  }
  t1 = (double)GetMicrosecondCount();
  dt1 = t1 - t0;
  // NormalizeDouble()
  t0 = (double)GetMicrosecondCount();
  for(int i = 1; i <= nstep; ++i)
  {
    v = step * i;
    vn[i - 1] = NormalizeDouble(v, digs);
  }
  t1 = (double)GetMicrosecondCount();
  dt2 = t1 - t0;
  Print(dt1, " ", dt2, " ", dt2 - dt1);
}