Un poco sorprendido :) Pensé en compartir y hacer una pregunta NO retórica. - página 23

 
Urain:

¿Vas a dividir uno (no necesariamente un múltiplo de 2) por otro (no necesariamente un múltiplo de 2) mediante un desplazamiento de bits?

Ok, voy a poner lo que tengo, y luego puedes decidir por ti mismo si lo necesitas o no.

Joseph Stein (1961):

gcd(n,0) = gcd(0, n) = n

gcd(n,n) = n

gcd(2n,2m) = 2gcd(n, m)

gcd(2n,2m + 1) = gcd(n, 2m + 1)

gcd(2n + 1, 2m) = gcd(2n + 1, m)

gcd(2n + 1, 2(n + k) + 1) = gcd(2(n + k) + 1, 2n + 1) = gcd(2n + 1, k)

--

Dos conferencias del creador de STL, Alexander Stepanov, en Yandex

// Sobre el tema del cálculo de NOD - segunda conferencia. Pero sugiero ver/escuchar a ambos. Conferencias geniales, hombre inteligente, simplemente agradable. Sí, y útil.
Archivos adjuntos:
gcd_ru.zip  365 kb
 
MetaDriver:
Si con los turnos de bits, ir a por ello. Si con la división del módulo, no.

Dividir por desplazamientos sucesivos

cifras interesantes al final del artículo:

Este algoritmo se ejecutará en el peor de los casos en (n-1)! iteraciones, donde n es la profundidad de bits del divisible. En resumen, en comparación con el algoritmo de adición secuencial, este algoritmo produce una ganancia de hasta 9 veces para números de 8 bits, y de hasta 546 veces para números de 16 bits.

 

Así que esto es lo que tengo:

long gcd(long m, long n) 
{
  if (m<0) m=-m; 
  if (n<0) n=-n;
  if (m==0) return n; 
  if (n==0) return m;
  int d = 0;
  while ((m & 1)==0 && (n & 1)==0) { m >>= 1; n >>= 1; ++d; }
  while ((m & 1)==0) m >>= 1;
  while ((n & 1)==0) n >>= 1;
  while (m!=n)   //  while (true)  // старый вариант 
    if (m < n) 
    {
      n -= m;
      do  n >>= 1;  while ((n & 1)==0);
    } 
    else       // if (n < m) это теперь без надобности
    {
      m -= n;
      do  m >>= 1;  while ((m & 1)==0);
    } 
//    else break;  // старый вариант
    return (m <<= d);
}

Parece que funciona bien. Por favor, comprueba todos los agujeros.

// Lo he retocado, es más bonito así.
Archivos adjuntos:
gcd.zip  1 kb
 

Es raro, no es muy rápido.

2011.04.03 22:56:59 gcdSpeedTest (EURUSD,M20) Tiempo común GreatestCommonDivisor(random(),random()) = 7656ms; // 10000000 llamadas
2011.04.03 22:56:51 gcdSpeedTest (EURUSD,M20) Tiempo común gcd(random(),random()) = 5234ms; // 10000000 llamadas

Archivos adjuntos:
gcd.zip  2 kb
 
MetaDriver:

Es raro, no es mucho más rápido.

2011.04.03 22:56:59 gcdSpeedTest (EURUSD,M20) Tiempo común GreatestCommonDivisor(random(),random()) = 7656ms; // 10000000 llamadas
2011.04.03 22:56:51 gcdSpeedTest (EURUSD,M20) Tiempo común gcd(random(),random()) = 5234ms; // 10000000 llamadas

Tengo una diferencia mayor. El tuyo es 3-4 veces más rápido, pero no olvides que en C++ la diferencia se reduce en un factor de 2-2,5, así que honestamente eres 1,5 veces más rápido.

void OnStart()
  {
//---
   int total=1000000;
   long x=2*3*5*7*9*11*13*17*19*21*23*29;
   long m=55*x,n=34*x;
   uint start=GetTickCount();
   for(int i=0;i<total;i++)x=gcd(m,n);      
   Print("MetaDriver gcd time=",GetTickCount()-start," x=",x);
   start=GetTickCount();
   for(int i=0;i<total;i++)x=GreatestCommonDivisor(m,n); 
   Print("Urain       GCD time=",GetTickCount()-start," x=",x);
  }
2011.04.03 22:35:41     Черновик 30 (EURUSD,M1) Urain       GCD time=1313 x=1222772020470
2011.04.03 22:35:40     Черновик 30 (EURUSD,M1) MetaDriver  gcd time= 312 x=1222772020470
 
Urain:

Tengo una diferencia mayor. El tuyo es 3-4 veces más rápido,

pero no olvides que en C++ la diferencia se reduce entre 2 y 2,5 veces, por lo que honestamente estás adelantado en 1,5 veces.


Y ya veremos.

Hasta ahora tenemos una versión preliminar en mql5. Pruebas amistosas, en busca de errores.

Lo he hecho como una estructura.

struct Rational
  {
   long              n;
   long              m;
   void ErrDZ() { Print("Rational error: zero-denominator!"); }
   void Neg() { n=-n; }
   void Norm() { long d=gcd(n,m); n/=d; m/=d; if (m<0) { n=-n; m=-m; } }
   void Assign(long a,long b) { if (b==0) { n=0; m=1; ErrDZ(); } if (b<0) { n=-a; m=-b; } else { n=a; m=b; } }
   void nAssign(long a,long b) { Assign(a,b); Norm(); }
   void Assign(long a) { Assign(a,1); }  // {n=a;m=1;}
   void Add(Rational &a) { if(m==a.m) n+=a.n; else { n*=a.m; n+=m*a.n; m*=a.m; } }
   void nAdd(Rational &a) { Add(a); Norm(); }
   void Add(long a) { n+=a*m; }
   void nAdd(long a) { Add(a); Norm(); }
   void Sub(Rational &a) { if(m==a.m) n-=a.n; else { n*=a.m; n-=m*a.n; m*=a.m; } }
   void nSub(Rational &a) { Sub(a); Norm(); }
   void Sub(long a) { n-=a*m; }
   void nSub(long a) { Sub(a); Norm(); }
   void Mul(Rational &a) { n*=a.n; m*=a.m; }
   void nMul(Rational &a) { Mul(a); Norm(); }
   void Mul(long a) { n*=a; }
   void nMul(long a) { Mul(a); Norm(); }
   void Div(Rational &a) { n*=a.m; m*=a.n; }
   void nDiv(Rational &a) { Div(a); Norm(); }
   void Div(long a) { m*=a; }
   void nDiv(long a) { Div(a); Norm(); }
   string ToString() {return "("+IntegerToString(n)+"/"+IntegerToString(m)+")";}
  };

He realizado todas las operaciones de dos formas: con y sin normalización. He conseguido una estructura flexible.

Si sospecha la posibilidad de desbordamiento - utilice una versión con normalización, si no - ahorre tiempo (puede normalizar más tarde, cuando la espuma se haya acumulado).

Hay una prueba sencilla en el archivo, pero es deseable hacer una prueba más dura.

Archivos adjuntos:
 
IgorM:

Gracias, al menos admítelo: cortaste los emoticonos, pero ¿quién elimina posts enteros?

Sobre eso, Académico, Me parece estupendo que tenga una supuesta "calculadora", pero me gustaría aclarar si se puede optimizar automáticamente en el transcurso de las operaciones.

Sí, es sólo un programa, si lo ejecutas, funcionará y te dará los parámetros óptimos.
 
Un control de la EMA sería una buena idea.
 

Especialmente para este hilo he publicado los últimos resultados del probador de MT5 (cualquiera podrá repetir las pruebas después de la próxima actualización).

Esto es lo que puede hacer el probador de MetaTrader 5, y más aún con diseños de infraestructura completa (informes, gráficos, resultados, visualización).

 
Renat:

Especialmente para este hilo he publicado los últimos resultados de MT5 tester (cualquiera podrá repetir las pruebas después de la próxima actualización).

Eso es lo que puede hacer el probador de MetaTrader 5, e incluso con un diseño completo (informes, gráficos, resultados, visualización).

7 símbolos, todos los ticks, desde el año 2000, dos parámetros ( variantes 200 * 200 )- 40000 pases, con cien órdenes por día para cada símbolo.

¿Cuánto tiempo tarda?

tomar 10 años - 356 * 10 * 100 * 7 = 25 000 000 operaciones

tomamos aproximadamente 10 ticks por minuto

y 10 años - 365 * 10 * 1440 * 10 = 52 000 000 ticks en un símbolo. Y si somos sinceros, están marcando todos los símbolos. Así que, sinceramente, deberíamos multiplicar por 7. Y no son 10 ticks por minuto. Y a veces son 300.


¿Cuánto tiempo tarda?

Razón de la queja: