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

 
Alexey Navoykov:

Apparentemente non intendi l'ereditarietà, ma un wrapper di una classe su una struttura?

giusto.
 
//+------------------------------------------------------------------+
//| Determines whether a set contains the specified element.         |
//+------------------------------------------------------------------+
template<typename T>
bool CHashSet::Contains(T item)
  {
//--- check buckets
   if(ArraySize(m_buckets)!=0)
     {
      //--- get hash code for item      
      int hash_code=m_comparer.HashCode(item)&0x7FFFFFFF;
      //--- search item in the slots       
      for(int i=m_buckets[hash_code%ArraySize(m_buckets)]-1; i>=0; i=m_slots[i].next)
         if(m_slots[i].hash_code==hash_code && m_comparer.Equals(m_slots[i].value,item))
            return(true);
     }
   return(false);
  }

Perché il bit del segno è tagliato?

 
fxsaber:

Perché il bit del segno è tagliato?

l'hash deve essere positivo perché agisce come un indice nell'array

 
TheXpert:

l'hash deve essere positivo perché agisce come un indice nell'array

uint?

 
fxsaber:

uint?

non ha senso

Документация по MQL5: Операции с массивами / ArraySize
Документация по MQL5: Операции с массивами / ArraySize
  • www.mql5.com
"Нулевое измерение = Размер массива / (Первое измерение * Второе измерение * Третье измерение)"
 
TheXpert:

non ha senso

La combinazione di linee evidenziate sembra sbagliata

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

Libreria di classi generiche - bug, descrizione, problemi, casi d'uso e suggerimenti

fxsaber, 2018.06.11 20:04

//+------------------------------------------------------------------+
//| Determines whether a set contains the specified element.         |
//+------------------------------------------------------------------+
template<typename T>
bool CHashSet::Contains(T item)
  {
//--- check buckets
   if(ArraySize(m_buckets)!=0)
     {
      //--- get hash code for item      
      int hash_code=m_comparer.HashCode(item)&0x7FFFFFFF;
      //--- search item in the slots       
      for(int i=m_buckets[hash_code%ArraySize(m_buckets)]-1; i>=0; i=m_slots[i].next)
         if(m_slots[i].hash_code==hash_code && m_comparer.Equals(m_slots[i].value,item))
            return(true);
     }
   return(false);
  }

Come si fa a confrontare un hashish tagliato con uno non tagliato?

 
fxsaber:

Come si fa a confrontare un hashish tagliato con uno non tagliato?

Penso che siano tutti troncati, anche se devo dire subito che ho guardato il codice solo brevemente e molto tempo fa, quindi potrei sbagliarmi.

Guarda il codice per aggiungere l'elemento.

 
TheXpert:

Penso che siano tutti tagliati, anche se devo dire subito che ho solo intravisto il codice molto tempo fa, quindi potrei sbagliarmi.

Guarda il codice per aggiungere un elemento.

//+------------------------------------------------------------------+
//| Insert the value with the specified key from the map.            |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
bool CHashMap::Insert(TKey key,TValue value,const bool add)
  {
   if(m_capacity==0)
      Initialize(0);
//--- get hash code from key
   int hash_code=m_comparer.HashCode(key)&0x7FFFFFFF;
   int target_bucket=hash_code%m_capacity;
//--- collisions count in one bucket with different hashes
   int collision_count=0;
//--- search pair with specified key
   for(int i=m_buckets[target_bucket]; i>=0; i=m_entries[i].next)
     {
      //--- hash compare      
      if(m_entries[i].hash_code!=hash_code)
        {
         collision_count++;
         continue;
        }
      //--- value compare     
      if(m_comparer.Equals(m_entries[i].key,key))
        {
         //--- adding duplicate
         if(add)
            return(false);
         m_entries[i].value=value;
         return(true);
        }
     }
//--- check collision
   if(collision_count>=m_collision_threshold)
     {
      int new_size=CPrimeGenerator::ExpandPrime(m_count);
      Resize(new_size);
     }
//--- calculate index
   int index;
   if(m_free_count>0)
     {
      index=m_free_list;
      m_free_list=m_entries[index].next;
      m_free_count--;
     }
   else
     {
      if(m_count==ArraySize(m_entries))
        {
         int new_size=CPrimeGenerator::ExpandPrime(m_count);
         Resize(new_size);
         target_bucket=hash_code%new_size;
        }
      index=m_count;
      m_count++;
     }
//--- set pair
   m_entries[index].hash_code=hash_code;
   m_entries[index].next=m_buckets[target_bucket];
   m_entries[index].key=key;
   m_entries[index].value=value;
   m_buckets[target_bucket]=index;
   return(true);
  }

Sì, grazie, solo che non ce ne sono che non siano tagliati nel codice. Strano che non abbiano fatto il trimming nel metodo HashCode stesso. Apparentemente il calcolo era per l'infallibilità (hash storti personalizzati).

 

Scusate se questo è già successo. Non l'ho trovato nella documentazione.

C'è qualche ciclo su Set-up? iteratore?

 
Viktor Lubimov:

Scusate se questo è già successo. Non l'ho trovato nella documentazione.

C'è qualche ciclo su Set-up?

Purtroppo no.
Ma potete implementarlo voi stessi.
Per esempio, vedere l'esempio dall'articoloMQL5 RECEIPTS - REALIZZARE UN DATABASE MASSIMO O MONDIALE ASSOCIATO PER UN RAPIDO ACCESSO AI DATI

void ReverseEnumerateAll(CList& list)
{
   CObject* node = list.GetLastNode();
   for(int i = list.Total()-1; node != NULL; i--, node = node.Prev())
      printf("Element at " + (string)i); 
}
Как работает этот код? На самом деле все просто. В функции EnumerateAll() в самом начале мы получаем ссылку на первый узел. Затем в цикле for мы печатаем порядковый узел этого узла 
и переходим к следующему узлу командой node = node.Next(), не забывая при этом проитерировать текущий индекс элемента на единицу (i++). Перебор продолжается до тех пор, пока текущий 
узел node не станет равен NULL, за это ответствен код во втором блоке for: node != NULL.

Аналогично работает реверсивная версия этой функции ReverseEnumerateAll() с той лишь разницей, что она вначале получает последний элемент списка CObject* node = list.GetLastNode(). 
В цикле for она получает не следующий, а предыдущий элемент списка node = node.Prev().