Biblioteca de clases genéricas - errores, descripción, preguntas, características de uso y sugerencias - página 8

 

Aquí está el código junto con el campo de entrada. (Puede ser útil para alguien. Puede ser refinado).

//+------------------------------------------------------------------+
//|                                                   Dictionary.mq5 |
//|                                                      Peter Konow |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Peter Konow"
#property link      ""
#property version   "1.00"
#property strict
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
#define  Max_possible_collisions    100
#define  Max_letters_in_word        100
#define  All_letters_in_alphabet    255 
//------------------------------------
string Dictionary[Max_possible_collisions][All_letters_in_alphabet][Max_letters_in_word];
//-------------------------------------------------------------------
int OnInit()
  {
//---
   Create_text_box();
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   ObjectDelete(0,"Text_box");
  }
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
    if(id == CHARTEVENT_OBJECT_ENDEDIT)
      { 
       //-----------------------
       string Text;     
       //---------------------
       ObjectGetString(0,"Text_box",OBJPROP_TEXT,0,Text);
       //-------------------------------------
       Add(Text);
      } 
  }
//+------------------------------------------------------------------+

void Add(string word)
{
 uchar First_letter = (uchar)StringGetCharacter(word,0) - 97;
 //-----------------------
 int All_letters_in_word = StringLen(word);
 //-----------------------
 for(int a1 = 0; a1 < Max_possible_collisions; a1++)
   {
     string word_inside = Dictionary[a1][First_letter][All_letters_in_word];
     //-----------------------   
    if(word_inside == NULL)
      {
       Dictionary[a1][First_letter][All_letters_in_word] = word;
       Print("Your word has been added to our dictionary!");
       break;
      }
    if(word_inside == word)
      {
       Print("This word already exists in our dictionary");
       break;
      } 
   }   
 //------------------------   
}
//--------------------------------------------------------------------+


//--------------------------------------------------------------------
void Create_text_box()
{
  ObjectCreate(0,"Text_box",OBJ_EDIT,0,0,0);
  ObjectSetInteger(0,"Text_box",OBJPROP_XDISTANCE,500);
  ObjectSetInteger(0,"Text_box",OBJPROP_YDISTANCE,250);
  ObjectSetInteger(0,"Text_box",OBJPROP_XSIZE,400);
  ObjectSetInteger(0,"Text_box",OBJPROP_YSIZE,30);
  ObjectSetString(0,"Text_box",OBJPROP_TEXT,"Please enter your word here...");
  ObjectSetString(0,"Text_box",OBJPROP_FONT,"TimesNewRoman");
  ObjectSetInteger(0,"Text_box",OBJPROP_STATE,1);
  //----------------------------------------------
  ObjectSetInteger(0,"Text_box",OBJPROP_FONTSIZE,12);
  ObjectSetInteger(0,"Text_box",OBJPROP_BGCOLOR,clrWhite);
  ObjectSetInteger(0,"Text_box",OBJPROP_COLOR,clrBlack);
  ObjectSetInteger(0,"Text_box",OBJPROP_BORDER_COLOR,clrBlack);
  ObjectSetInteger(0,"Text_box",OBJPROP_ALIGN,ALIGN_CENTER);
  //----------------------------------------------
  ObjectSetInteger(0,"Text_box",OBJPROP_CORNER,CORNER_LEFT_UPPER);
  ObjectSetInteger(0,"Text_box",OBJPROP_ANCHOR,ANCHOR_LEFT_UPPER);  
  //---------------------------------------------- 
}
//----------------------------------------------------------------------- 

Sólo que por alguna razón, funciona completamente en el cuarto. En el quinto, el campo no aparece. He buscado el motivo y no lo he encontrado.

 
fxsaber:

Es decir, hay que encontrar el equilibrio adecuado entre el tamaño del diccionario (RAM) y la complejidad computacional de la función hash (CPU) para cada tarea.


Relativamente sí.
Cuando el número de elementos es pequeño, el tamaño óptimo del diccionario es el número de elementos al cuadrado (por lo que recuerdo del curso de 3 años, pero siempre es mejor volver a comprobarlo).
Cuando un gran número de elementos hace imposible elegir el tamaño óptimo, toman el tamaño del diccionario varias veces mayor que el número de elementos esperados y optimizan la gestión de las colisiones, por ejemplo, utilizando tablas hash internas para cada una de ellas.

Se intenta elegir una tabla hash para que la búsqueda sea lo más rápida posible, pero que proporcione una distribución uniforme de los resultados obtenidos sobre el tamaño de la lista de palabras.
El uso de números primos en los hashes está relacionado con la uniformidad de la distribución.

 
Etiqueta Konow:
Hemos tenido que aumentar el tamaño de la matriz, porque las mayúsculas tienen un código diferente y "se salen" de la matriz.

El código del carácter "A" difiere del código del carácter "a" exactamente en 32. En consecuencia, todos los demás tienen la diferencia de 32 también.

Tal vez no se debería haber aumentado el tamaño de la matriz y se debería haber sustituido el primer carácter.
 
Alexey Viktorov:

El código del carácter "A" difiere del código del carácter "a" exactamente en 32. En consecuencia, todos los demás también tienen una diferencia de 32.

Tal vez no se debería haber aumentado el tamaño de la matriz y se debería haber sustituido el primer carácter.

Estoy de acuerdo. El algoritmo es incompleto en este sentido.

El tamaño de la matriz es demasiado grande. Ayer no entendí del todo los códigos de las letras.

 
Etiqueta Konow:

Aquí está el código junto con el campo de entrada. (Puede serle útil a alguien. Puede perfeccionarlo).

Pero funciona perfectamente en el 4. El campo no aparece en el cinco. He buscado el motivo y no lo he encontrado.

Una observación más: en el ejemplo de Vasiliy se menciona una matriz

Foro sobre comercio, sistemas de comercio automatizados y pruebas de estrategias

Biblioteca de clases genéricas - errores, descripciones, preguntas, peculiaridades de uso, sugerencias

Vasiliy Sokolov, 2017.12.07 14:30

Muy simple en el array asociativo #1

Muchos de los algoritmos que se presentan en Generic se basan en matrices asociativas o diccionarios. También es uno de los dos algoritmos más utilizados. Creo que estaría cerca de la verdad si dijera que el 90% de las tareas de programación se cubren con arrays y diccionarios. Antes de pasar a la práctica, vamos a describir el trabajo del diccionario de la forma más clara y sencilla posible, simplificando deliberadamente algunos detalles.

Mostraremos el diccionario en un ejemplo muy sencillo: una lista de palabras regulares. Supongamos que tenemos unas pocas palabras, que empiezan con diferentes letras del alfabeto:

string words[] = {"apple", "cat", "fog", "dog", "walk", "zero"};

El alfabeto inglés contiene 26 caracteres. Vamos a crear un array de cadenas, de tamaño 26 elementos:

string dictionary[26];

Ahora bien, si aceptamos almacenar las palabras en índices correspondientes a su primera letra, obtendremos un diccionario sencillo. Vamos a indexar desde cero. La palabra "manzana" se almacenará en nuestro diccionario en el índice 0, porque el carácter "a" es la primera letra del alfabeto, "gato" - en el índice 1, "perro" - en el índice 3, niebla - ocupará el índice 4, paseo - índice 24 y cero - el último índice 25.

Tenga en cuenta que los índices 5 a 23 no se utilizarán. Esto supone un gasto adicional de memoria, pero podemos acceder instantáneamente, por ejemplo, a la palabra "paseo", porque sabemos que si existe, se encuentra en el índice 24.

Vamos a escribir nuestro primer diccionario vacío:



Y en su ejemplo.

#define  Max_possible_collisions    100
#define  Max_letters_in_word        100
#define  All_letters_in_alphabet    255 
//------------------------------------
string Dictionary[Max_possible_collisions][All_letters_in_alphabet][Max_letters_in_word];

¿Cuánta memoria ocupa una matriz tridimensional? ¿Y si tengo que aumentar la dimensionalidad?

 
Alexey Viktorov:

Una nota más: En el ejemplo de Vasiliy se menciona un array


Y en su ejemplo.

¿Cuánta memoria ocupa una matriz tridimensional? ¿Y si tenemos que aumentar la dimensionalidad?

El tamaño del array es demasiado grande porque:

1. He decidido que el número máximo de letras en una palabra puede ser 100. Esto es obviamente demasiado. Podríamos reducirlo a 30.

2. El número de letras posibles también resultó ser excesivo. Decidí dar cabida al mayor número posible de personajes diferentes. Se puede reducir.

3. El número de "colisiones", es decir, la coincidencia de palabras por la primera letra y por el número de letras de la palabra, se fija en 100. Esto también es demasiado. Podrías bajar a 50.


No veo la razón para aumentarla. Puede añadir un diccionario.

 
Etiqueta Konow:

El tamaño de la matriz es demasiado grande porque:

1. He decidido que el número máximo de letras de una palabra puede ser 100. Esto es claramente una exageración. Podría reducirse a 30.

2. El número de letras posibles también resultó ser excesivo. Decidí dar cabida al mayor número posible de personajes diferentes. Se puede reducir.

3. El número de "colisiones", es decir, la coincidencia de palabras por la primera letra y por el número de letras de la palabra, se fija en 100. Esto también es demasiado. Puedes reducirlo a 50.


No veo ninguna razón para aumentar el tamaño. Puede hacer otro diccionario.

La pregunta no se refiere al diccionario. El diccionario es sólo un ejemplo de cómo construir un algoritmo. Puede que no haya ni de lejos 100 artículos como en tu ejemplo, sino 1e10 y más... ¿Cuál es el tamaño de la matriz en ese caso?

Por ejemplo, recoger todo el historial de ticks disponible en una matriz. Puede haber más de un tick en un milisegundo, por lo que el array no puede ser unidimensional... ¿Cuántos ticks hubo en un milisegundo como máximo? ¿Dos o cinco? ¿Cuál debería ser la dimensionalidad del array en este caso? ¿Cuánta memoria se desperdiciaría?

 
Alexey Viktorov:

Por ejemplo, recoger todo el historial de ticks disponible en una matriz.

Después de escribir todo esto, se me ocurrió que no hay ninguna tarea práctica para almacenar las garrapatas en la forma discutida en el hilo. Se ordenan por tiempo y se almacenan en un simple array.

Lo mismo ocurre con los Pedidos/Ofertas de Historia. Y, a juzgar por HistorySelect, se almacenan en una matriz por tiempo. Y creo que no hay nada (en la implementación actual) que permita buscar registros por ticket o por ID.

Y todo porque en el caso de la historia nombrada no es razonable hacer algo así. Una simple matriz para practicar es suficiente.

Por eso me interesa la redacción práctica de las tareas en el ámbito del comercio.


Cuando se trata de acelerar HistorySelect, estoy seguro de que resolvió el problema con el almacenamiento en caché, no con hashes y diccionarios.

 
fxsaber:

Después de escribir todo esto, se me ocurrió que no hay ninguna tarea práctica para almacenar las garrapatas de la manera discutida en el hilo. Se ordenan por tiempo y se almacenan en un simple array.

Lo mismo ocurre con los Pedidos/Ofertas de Historia. Y, a juzgar por HistorySelect, se almacenan en una matriz por tiempo. Y creo que no hay nada (en la implementación actual) que permita buscar registros por ticket o por ID.

Y todo porque en el caso de la historia nombrada no es razonable hacer algo así. Una simple matriz para practicar es suficiente.

Por eso me interesa la redacción práctica de las tareas en el ámbito del comercio.


Cuando se acelera HistorySelect, probablemente se ha resuelto con el almacenamiento en caché, no con los diccionarios hash.

No se discute, pero si alguien quiere implementar alguna tarea de esa manera, entonces se marca en el lugar...

Alguien piensa que no tiene sentido, alguien no puede dominarlo... Y en ambos casos hay implementaciones más sencillas. Pero quién sabe cómo se desarrollará el comercio "mañana"... Probablemente sea mejor tenerla y que no sea reclamada que ser necesaria en ausencia de la misma.

 
Alexey Viktorov:

La pregunta no se refiere al diccionario. El diccionario es sólo un ejemplo de construcción de algoritmos. Y puede que no haya ni de lejos 100 artículos como en tu ejemplo, sino 1e10 y más... ¿Cuál es el tamaño de la matriz en ese caso?

Por ejemplo, reunir todo el historial de ticks disponible en una matriz. Puede haber más de un tick en un milisegundo, por lo que el array no puede ser unidimensional... ¿pero cuántos ticks hubo en un milisegundo como máximo? ¿Dos o cinco? ¿Cuál debería ser la dimensionalidad del array en este caso? ¿Cuánta memoria se desperdicia?

Estaba resolviendo la tarea de construir un diccionario conveniente.

Las garrapatas u otros elementos tienen sus propias propiedades específicas, que se pueden indexar con éxito para acceder rápidamente a la ubicación de almacenamiento.

La esencia de la tarea de acceso rápido a los datos, es identificar varias propiedades clasificables de un elemento e indexarlas.

Se toma un elemento, se encuentran las propiedades convenientes de las que se pueden obtener índices y se accede al almacén a través de los índices.

Si los índices no son suficientes (por ejemplo, podemos indexar la primera letra y el número de letras, pero otras propiedades no proporcionan un índice conveniente), hacemos una fuerza bruta directa de los elementos dentro del área que lo rodea.

El principio es universal, las aplicaciones pueden variar.

Razón de la queja: