Libreria di classi generiche - bug, descrizione, domande, caratteristiche d'uso e suggerimenti - pagina 8

 

Ecco il codice insieme al campo di input. (Può tornare utile a qualcuno, può essere raffinato).

//+------------------------------------------------------------------+
//|                                                   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);  
  //---------------------------------------------- 
}
//----------------------------------------------------------------------- 

Solo che, per qualche motivo, funziona completamente sul quarto. Al quinto, il campo non appare. Ho cercato il motivo e non l'ho trovato.

 
fxsaber:

Cioè devi trovare il giusto equilibrio tra la dimensione del dizionario (RAM) e la complessità computazionale della funzione hash (CPU) per ogni compito.


Relativamente sì.
Quando il numero di elementi è piccolo, la dimensione ottimale del dizionario è il numero di elementi al quadrato (per quanto ricordo dal corso di 3 anni, ma è sempre meglio ricontrollare).
Quando un gran numero di elementi rende impossibile scegliere la dimensione ottimale, prendono la dimensione del dizionario diverse volte più grande del numero di elementi previsti e ottimizzano la gestione delle collisioni, per esempio, utilizzando tabelle hash interne per ogni collisione.

Si cerca di scegliere una tabella hash in modo che sia ricercata il più velocemente possibile, ma che fornisca comunque una distribuzione uniforme dei risultati ottenuti sulla dimensione della lista di parole.
L'uso dei numeri primi negli hash è legato all'uniformità della distribuzione.

 
Konow tag:
Abbiamo dovuto aumentare la dimensione dell'array, perché le lettere maiuscole hanno un codice diverso e "escono" dall'array.

Il codice del carattere "A" differisce dal codice del carattere "a" esattamente di 32. Corrispondentemente, anche tutti gli altri hanno la differenza di 32.

Forse la dimensione dell'array non doveva essere aumentata e il primo carattere doveva essere sostituito.
 
Alexey Viktorov:

Il codice del carattere "A" differisce dal codice del carattere "a" esattamente di 32. Di conseguenza, anche tutti gli altri hanno una differenza di 32.

Forse la dimensione dell'array non doveva essere aumentata e il primo carattere doveva essere sostituito.

Sono d'accordo. L'algoritmo è incompleto in questo senso.

La dimensione dell'array è troppo grande. Ieri non ho capito del tutto i codici delle lettere.

 
Tag Konow:

Ecco il codice insieme al campo di input. (Può tornare utile a qualcuno, puoi perfezionarlo).

Ma funziona perfettamente sul 4. Il campo non appare su cinque. Ho cercato il motivo e non l'ho trovato.

Un'altra osservazione: nell'esempio di Vasiliy si parla di un array

Forum sul trading, sistemi di trading automatico e test di strategia

Libreria di classi generiche - errori, descrizioni, domande, peculiarità d'uso, suggerimenti

Vasiliy Sokolov, 2017.12.07 14:30

Molto semplice nell'array associativo #1

Molti algoritmi che sono presentati in Generico sono basati su array associativo o dizionario. È anche uno dei due algoritmi più utilizzati. Penso di essere vicino ad avere ragione quando dico che il 90% di tutti i compiti di programmazione sono coperti da array e dizionari. Prima di passare alla pratica, descriviamo il lavoro del dizionario nel modo più chiaro e diretto possibile, semplificando deliberatamente alcuni dettagli.

Mostreremo il dizionario su un esempio molto semplice: un elenco di parole regolari. Supponiamo di avere solo alcune parole, che iniziano tutte con lettere diverse dell'alfabeto:

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

L'alfabeto inglese contiene 26 caratteri. Creiamo un array di stringhe, di 26 elementi:

string dictionary[26];

Ora, se accettiamo di memorizzare le parole in indici corrispondenti alla loro prima lettera, otterremo un semplice dizionario. Indicizzeremo da zero. La parola 'mela' sarà memorizzata nel nostro dizionario all'indice 0, perché il carattere 'a' è la prima lettera dell'alfabeto, 'gatto' - all'indice 1, 'cane' - all'indice 3, nebbia - occuperà l'indice 4, passeggiata - indice 24 e zero - l'ultimo indice 25.

Si noti che gli indici da 5 a 23 non saranno utilizzati. Questo è un ulteriore spreco di memoria, ma possiamo accedere istantaneamente ad esempio alla parola "walk", perché sappiamo che se esiste, si trova all'indice 24.

Scriviamo il nostro primo dizionario vuoto:



E nel suo esempio.

#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];

Quanta memoria prende un array tridimensionale? E se devo aumentare la dimensionalità?

 
Alexey Viktorov:

Un'altra nota: nell'esempio di Vasiliy si parla di un array


E nel suo esempio.

Quanta memoria prende un array tridimensionale? E se dovessimo aumentare la dimensionalità?

Ladimensione dell'array è troppo grande perché:

1. Ho deciso che il numero massimo di lettere in una parola può essere 100. Questo è ovviamente troppo. Potremmo ridurlo a 30.

2. Anche il numero di lettere possibili si è rivelato eccessivo. Ho deciso di dare spazio al maggior numero possibile di personaggi diversi. Può essere ridotto.

3. Il numero di "collisioni", cioè la corrispondenza delle parole per la prima lettera e per il numero di lettere nella parola, è impostato su 100. Anche questo è troppo. Si può scendere a 50.


Non vedo la ragione per aumentarlo. Si può semplicemente aggiungere un dizionario.

 
Tag Konow:

La dimensione dell'array è troppo grande perché:

1. Ho deciso che il numero massimo di lettere in una parola può essere 100. Questo è chiaramente eccessivo. Potrebbe essere ridotto a 30.

2. Anche il numero di lettere possibili si è rivelato eccessivo. Ho deciso di dare spazio al maggior numero possibile di personaggi diversi. Può essere ridotto.

3. Il numero di "collisioni", cioè la corrispondenza delle parole per la prima lettera e per il numero di lettere nella parola è impostato su 100. Anche questo è troppo. Si può ridurre a 50.


Non vedo alcuna ragione per aumentare le dimensioni. Potresti fare un altro dizionario.

La domanda non riguarda il dizionario. Il dizionario è solo un esempio di come costruire un algoritmo. Ci possono essere molto meno di 100 articoli come nel tuo esempio, ma 1e10 e più... Qual è la dimensione dell'array in questo caso?

Per esempio, raccogliere tutta la cronologia dei tick disponibile in un array. Ci può essere più di un tick in un millisecondo, quindi l'array non può essere unidimensionale... Quanti tic c'erano al massimo in un millisecondo? Due o cinque? Quale dovrebbe essere la dimensionalità dell'array in questo caso? Quanta memoria verrebbe sprecata?

 
Alexey Viktorov:

Per esempio, raccogliere tutta la cronologia dei tick disponibile in un array.

Dopo aver scritto tutto questo, mi è venuto in mente che non c'è nessun compito pratico per memorizzare i tick nel modo discusso nel thread. Sono ordinati per tempo e memorizzati in un semplice array.

È la stessa cosa con gli ordini/le offerte della storia. E, a giudicare da HistorySelect, sono memorizzati in un array in base al tempo. E credo che non ci sia nulla (nell'implementazione attuale) che permetta di cercare i record per biglietto o ID.

E tutto perché nel caso della storia nominata non è ragionevole fare una cosa del genere. Una semplice matrice per la pratica è sufficiente.

Ecco perché sono interessato alla formulazione pratica dei compiti nel campo del trading.


Quando stai cercando di velocizzare HistorySelect, sono sicuro che hai risolto il problema con la cache, non con hash e dizionari.

 
fxsaber:

Dopo aver scritto tutto questo, mi è venuto in mente che non c'è nessun compito pratico per memorizzare i tick nel modo discusso nel thread. Sono ordinati per tempo e memorizzati in un semplice array.

È lo stesso per gli ordini/le offerte della storia. E, a giudicare da HistorySelect, sono memorizzati in un array in base al tempo. E credo che non ci sia nulla (nell'implementazione attuale) che permetta di cercare i record per biglietto o ID.

E tutto perché nel caso della storia nominata non è ragionevole fare una cosa del genere. Una semplice matrice per la pratica è sufficiente.

Ecco perché sono interessato alla formulazione pratica dei compiti nel campo del trading.


Quando si velocizza HistorySelect, probabilmente si è risolto con la cache, non con i dizionari hash.

Nessuna discussione, ma se qualcuno vuole implementare qualche compito in quel modo, allora segnalatelo sul posto...

Qualcuno pensa che non abbia senso, qualcuno non riesce a padroneggiarlo... E in entrambi i casi ci sono implementazioni più semplici. Ma chissà come si svilupperà il trading "domani"... Probabilmente è meglio averla e rimanere non reclamata che averla necessaria in assenza di essa.

 
Alexey Viktorov:

La domanda non riguarda il dizionario. Il dizionario è solo un esempio di costruzione di un algoritmo. E ci possono essere molto meno di 100 articoli come nel tuo esempio, ma 1e10 e più... Qual è la dimensione dell'array in questo caso?

Per esempio, raccogliete tutta la cronologia dei tick disponibile in un array. Ci può essere più di un tick in un millisecondo, quindi l'array non può essere unidimensionale... ma quanti tic c'erano in un millisecondo al massimo? Due o cinque? Quale dovrebbe essere la dimensionalità dell'array in questo caso? Quanta memoria verrà sprecata?

Stavo risolvendo il compito di costruire un dizionario conveniente.

Le zecche o altri elementi hanno le loro proprietà specifiche, che possono essere indicizzate con successo per un accesso rapido alla posizione di memorizzazione.

L'essenza del compito di accesso veloce ai dati, è identificare diverse proprietà classificabili di un elemento e indicizzarle.

Si prende un elemento, si trovano le proprietà convenienti da cui si possono ottenere indici, e l'accesso alla posizione di memorizzazione si ottiene attraverso gli indici.

Se gli indici non sono sufficienti (per esempio, possiamo indicizzare la prima lettera e il numero di lettere, ma le altre proprietà non forniscono un indice conveniente), facciamo un bruteforcing diretto degli elementi all'interno dell'area circostante.

Il principio è universale, le implementazioni possono variare.

Motivazione: