Получаем количество десятичных знаков после запятой любых чисел (не только котировок) в обход Digits() на MQL4 и MQL5 - страница 22

 
Andrey Khatimlianskii:

Мне не нужно.

Назвался груздем, да?.. 

Вот массив из 10000 элементов, полностью случайный, рандомизируемый перед каждым циклом каждой сортировки. Суммарное время (мс) за 1000 повторений каждого метода.

Встроенный ArraySort, мой метод написанный пару дней назад (до этого я вообще алгоритмами сортировки не занимался), и 6 лучших методов из вашей библиотеки (остальные были значительно хуже), при том, что я все, что было связано с графикой, от-туда убрал...

#include <Sort\GSort.mqh>
#define   ttt                 template<typename T>
#define   test(M,S,EX)        {uint mss=GetTickCount();int nn=(int)pow(10,M);for(int tst=0;tst<nn&&!_StopFlag;tst++){EX;} \
                                printf("%s: loops=%i ms=%u",S,nn,GetTickCount()-mss);}


ttt void a_rand(T&ar[]){for(int i=0;i<ArraySize(ar);i++)ar[i]=T(rand()*rand());}

ttt int TreePop(T&t[],T&ar[],int i=0,int b=0)
 {
  if(t[b+1]>=0)i=TreePop(t,ar,i,(int)t[b+1]);
  ar[i++]=t[b];
  if(t[b+2]>=0)i=TreePop(t,ar,i,(int)t[b+2]);
  return i;
 }

ttt void TreeSort(T&ar[])
 {
  int sz=ArrayRange(ar,0);
  T t[];ArrayResize(t,sz*3);ArrayInitialize(t,-1);
  for(int i=0;i<ArraySize(ar);i++){t[i*3]=ar[i];
    if(!i)continue;
    int b=0;
    while(1)
      if(ar[i]<=t[b])
        if(t[b+1]>=0)b=(int)t[b+1];
        else{t[b+1]=i*3;break;}
      else
        if(t[b+2]>=0)b=(int)t[b+2];
        else{t[b+2]=i*3;break;}}
  TreePop(t,ar);
 }


void OnStart(){
  double ar[];
  int N=10000,k=3;
  ArrayResize(ar,N);

  test(k,"ArraySort(MQL5)",a_rand(ar);ArraySort(ar))
  test(k,"TreeSort(AntFX)",a_rand(ar);TreeSort(ar))
  test(k,"Merge(GSort)",a_rand(ar);GMergesort(ar,0,N-1))
  test(k,"QTernaryLL(GSort)",a_rand(ar);GQSortTernaryLL(ar,0,N-1))
  test(k,"QSortLL(GSort)",a_rand(ar);GQSortTernaryLL(ar,0,N-1))
  test(k,"QSort(GSort)",a_rand(ar);GQSortTernaryLR(ar,0,N-1))
  test(k,"QTernaryLR(GSort)",a_rand(ar);GQSortTernaryLR(ar,0,N-1))
  test(k,"Comb(GSort)",a_rand(ar);GComb(ar))
}
 
Ilya Malev:

Назвался груздем, да?.. 

Вот массив из 10000 элементов, полностью случайный, рандомизируемый перед каждым циклом каждой сортировки. Суммарное время (мс) за 1000 повторений каждого метода.

Встроенный ArraySort, мой метод написанный пару дней назад (до этого я вообще алгоритмами сортировки не занимался), и 6 лучших методов из вашей библиотеки (остальные были значительно хуже), при том, что я все, что было связано с графикой, от-туда убрал...

Судя по видео из статьи, самые быстрые — Count, LSD и MSD.

 
Andrey Khatimlianskii:

Судя по видео из статьи, самые быстрые — Count, LSD и MSD.

Завершения этих проходов я так и не дождался.

 
Alexandr Sokolov:

Думаю не у одного меня была редкая ситуация когда нужно было получить количество десятичных знаков после запятой, а функция Digits() работает только с котировками, и к тому всему ещё и информации по этому поводу нигде нет (по крайней мере на момент написания этого поста ранее её я не находил, поэтому хочу показать какое решение нашел я)?


Как оказалось суть банально простая, но всё же имеет один недостаток - эта функция не распознаёт нули если после них нет иных цифр. Например если функции дать число 0,01 она вернёт 2, а если 0,0000 она вернёт 0 (то есть четыре нуля она не видит). Поэтому учитывайте этот недостаток в своих разработках


Код на MQL4


Код на MQL5

Код на MQL5 пришлось немного доработать, так как по всей видимости на MQL5 для переменных типа double автоматически присваивается ,0 в конце вне зависимости от того целое число ей присваивается или нет. И по этой причине функция никогда не возвращала 0

если тема актуальна, то вот мой вариант:

int kol_Z(double zzz) { // вычисляем кол-во знаков после запятой

  string a, d;
  int b, c;
  a=StringFormat("%g", zzz);
  b=StringFind(a,".",0);
  c=StringLen(a);
  if (b==-1) return(0);
  d=StringSubstr(a,b+1);
  return(StringLen(d));
}
 
NomadSoul:

если тема актуальна, то вот мой вариант:

Пример:

void OnStart()
{
    Print(kol_Z(1.001234));
}

Результат: 5, а должно быть 6

 
A100:

Пример:

Результат: 5, а должно быть 6

https://www.mql5.com/ru/forum/360632 - по сути, та же тема "Самый простой способ посчитать количество знаков после запятой?". Как можно, дав компьютеру число, которое он обязан обрезать до длины имеющейся у него мантиссы, после этого спрашивать у него, а где же там был конец этой бесконечной периодической дроби?

0.0001100110011001100110011(0011)  - десятичное число 0.1 в двоичном представлении. В скобках периодическая часть бесконечной дроби. Так что же должен ответить компьютер, если в double у него хранятся лишь первые 52 значащие цифры из бесконечного их числа?

Никого не удивляет, что у очень короткого троичного числа 0.1 в десятичном представлении (0.33333...) бесконечное число значащих цифр после запятой. Двоичное 0.1 равно десятичному 0.5 с конечным числом знаков по счастливой случайности, нашелся и сократился общий делитель у двух оснований систем счисления 2 и 10, это 2. Хороши и степени половины в обоих представлениях: 0.5 => 0.1; 0.05 => 0.01 ; 0.025 => 0.001 ; 0.0125 => 0.0001. Но как только в знаменателе дроби появляется 5 - все, значащих цифр немеряно много.

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

Самый простой способ посчитать количество знаков после запятой?
Самый простой способ посчитать количество знаков после запятой?
  • 2021.01.18
  • www.mql5.com
Есть переменная. Например: double а=0.02; Нужно написать функцию, которая считала бы количество знаков после запятой...
 

1

Три раза запускал. Прям в гриву дышит лидеру... Если кому надо, функция здесь - https://www.mql5.com/ru/code/904, имя функции - SortHoareUp.

 
Dmitry Fedoseev:

Три раза запускал. Прям в гриву дышит лидеру... Если кому надо, функция здесь - https://www.mql5.com/ru/code/904, имя функции - SortHoareUp.

Есть ещё MathQuickSort() из стат. библиотеки (#include <Math\Stat\Math.mqh>). Помнится, была статья где писали, что очень-очень быстрая библиотека)

Скорость не мерил, в основном пользуюсь из-за возможности сохранять массив индексов исходного массива.

 
Vladimir:

https://www.mql5.com/ru/forum/360632 - по сути, та же тема "Самый простой способ посчитать количество знаков после запятой?". Как можно, дав компьютеру число, которое он обязан обрезать до длины имеющейся у него мантиссы, после этого спрашивать у него, а где же там был конец этой бесконечной периодической дроби?

0.0001100110011001100110011(0011)  - десятичное число 0.1 в двоичном представлении. В скобках периодическая часть бесконечной дроби. Так что же должен ответить компьютер, если в double у него хранятся лишь первые 52 значащие цифры из бесконечного их числа?

Никого не удивляет, что у очень короткого троичного числа 0.1 в десятичном представлении (0.33333...) бесконечное число значащих цифр после запятой. Двоичное 0.1 равно десятичному 0.5 с конечным числом знаков по счастливой случайности, нашелся и сократился общий делитель у двух оснований систем счисления 2 и 10, это 2. Хороши и степени половины в обоих представлениях: 0.5 => 0.1; 0.05 => 0.01 ; 0.025 => 0.001 ; 0.0125 => 0.0001. Но как только в знаменателе дроби появляется 5 - все, значащих цифр немеряно много.

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

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

Если же вопрос о том, какое целое число подавать вторым аргументом в функцию NormalizeDouble(), то ответ нужно искать с помощью этой же функции. Это будет минимальное целое число от 0 до 8, для которого нормализованное число будет равно исходному. Если не найдётся такого целого, то исходное число неправильное. Вот пример кода, где число знаков считается для минимального шага объёма.