Bibliothèque de classes génériques - bogues, description, questions, caractéristiques d'utilisation et suggestions - page 22

 
Alexey Navoykov:

Apparemment, vous ne voulez pas parler d'héritage, mais d'une enveloppe d'une classe sur une structure ?

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

Pourquoi le bit de signe est-il coupé ?

 
fxsaber:

Pourquoi le bit de signe est-il coupé ?

le hash doit être positif car il agit comme un index dans le tableau

 
LeXpert:

le hash doit être positif car il agit comme un index dans le tableau

uint ?

 
fxsaber:

uint ?

n'a aucun sens

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

n'a aucun sens

La combinaison des lignes en surbrillance ne semble pas correcte

Forum sur le trading, les systèmes de trading automatisés et les tests de stratégies de trading

Bibliothèque de classes génériques - bogues, description, problèmes, cas d'utilisation et suggestions

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

Comment comparez-vous un hachis paré à un hachis non paré ?

 
fxsaber:

Comment comparez-vous un hachis paré à un hachis non paré ?

Je pense qu'ils sont tous tronqués, bien que je doive dire tout de suite que je n'ai regardé le code que brièvement et il y a longtemps, donc je peux me tromper.

Regardez le code pour ajouter l'élément.

 
LeXpert:

Je pense qu'ils sont tous coupés, même si je dois dire tout de suite que je n'ai jeté qu'un coup d'œil au code il y a longtemps, donc je peux me tromper.

Regardez le code pour ajouter un élément.

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

Oui merci, il n'y en a pas qui ne soient pas rognés dans le code. C'est bizarre qu'ils n'aient pas fait le découpage dans la méthode HashCode elle-même. Apparemment, le calcul était destiné à éviter les erreurs (hachages personnalisés erronés).

 

Désolé si cela s'est déjà produit. Je ne l'ai pas trouvé dans la documentation.

Y a-t-il une boucle sur l'itérateur Set-ups ?

 
Viktor Lubimov:

Désolé si cela s'est déjà produit. Je ne l'ai pas trouvé dans la documentation.

Y a-t-il une boucle sur les réglages ?

Malheureusement, non.
Mais vous pouvez le mettre en œuvre vous-même.
Voir par exemple l'exemple de l'articleRECETTES MQL5 - RÉALISER UNE BASE DE DONNÉES MASSIVE OU MONDIALE ASSOCIÉE POUR UN ACCÈS RAPIDE AUX DONNÉES

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().