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

 
Sergey Dzyublik:

1. Éliminez les comportements ambigus :
Si nous passons "INT_MAX - 10" comme paramètre à CPrimeGenerator::ExpandPrime, le résultat "INT_MAX" sera renvoyé.
Si nous passons "INT_MAX - 10" comme paramètre à CPrimeGenerator::GetPrime, le même résultat sera renvoyé : "INT_MAX - 10".

Dans les deux cas, la valeur renvoyée n'est pas un nombre premier, ce qui induit l'utilisateur en erreur.

Sur le premier point :

Il n'y a aucune ambiguïté ici.

La méthode GetPrime devrait renvoyer le nombre premier le plus proche, mais sur l'intervalle de INT_MAX - 10 à INT_MAX, il n'y en a pas, c'est pourquoi INT_MAX - 10 est renvoyé.

La méthode ExpandPrime double d'abord la valeur d'entrée et la méthode GetPrime est appelée à partir du nombre reçu.

En outre, ExpandPrime a une vérification pour le dépassement de INT_MAX :

   if((uint)new_size>INT_MAX && INT_MAX>old_size)
      return INT_MAX;
   else
      return GetPrime(new_size);

À mon avis, la logique qui sous-tend le comportement de ces méthodes est absolument sans ambiguïté et correcte.


En ce qui concerne les deuxième et troisième points :

Les changements que vous suggérez ne sont pertinents, pour la plupart, que pour les problèmes de bord, lorsque les tailles de CHashMap sont très grandes. Cependant, il n'y a aucune garantie qu'ils auront un impact positif sur les performances. Des études distinctes doivent donc être réalisées pour déterminer la justesse des changements que vous suggérez.

 
Roman Konopelko:

Il n'y a aucune ambiguïté ici.
La méthode GetPrime devrait renvoyer le nombre premier le plus proche, mais il n'y en a aucun entre INT_MAX - 10 et INT_MAX, donc INT_MAX - 10 est renvoyé.
La méthode ExpandPrime double d'abord la valeur d'entrée et la méthode GetPrime est appelée à partir du nombre reçu.
En outre, ExpandPrime a une vérification pour le dépassement de INT_MAX :
La logique du comportement de ces méthodes est absolument sans ambiguïté et correcte.


1. Les fonctions peuvent renvoyer des nombres inconnus au lieu de nombres premiers.
La façon dont l'utilisateur utilise ces données est son problème, peut-être qu'il les intègre dans le long et les transmet ensuite aux fonctions de supercalcul, peu importe.
Le fait est que nous pouvons retourner quelque chose de différent de ce qui est déclaré et attendu des fonctions par défaut.

2. Comment vérifier que l'appel de la fonction a retourné un nombre premier et non autre chose ?
Vous ne pouvez pas simplement le comparer à INT_MAX.
Vous devez le comparer avec le dernier nombre premier disponible inférieur à INT_MAX.
Chaque fois que l'on compare le résultat des appels de ces fonctions à un nombre magique pour s'assurer que tout va bien, je trouve cela absurde.

 
Sergey Dzyublik:

1. Les fonctions peuvent ne pas renvoyer des nombres premiers, mais des nombres obscurs.
La façon dont l'utilisateur utilise ces données est son problème. Il peut les convertir en données longues et les transmettre ensuite à des fonctions de supercalcul, peu importe.
Le fait est que nous pouvons retourner quelque chose de différent de ce qui est déclaré et attendu des fonctions par défaut.

2. Comment vérifier que l'appel de la fonction a retourné un nombre premier et non autre chose ?
Vous ne pouvez pas simplement le comparer à INT_MAX.
Vous devez le comparer avec le dernier nombre premier disponible inférieur à INT_MAX.
Comparer le résultat de chaque appel de ces fonctions avec un nombre magique à chaque fois pour s'assurer que tout est correct, me semble absurde.

1. Votre cas d'obtention d'un nombre non simple à l'aide de la méthode GetPrime est le seul que j'ai rencontré jusqu'à présent. Cet incident sera corrigé en modifiant la vérification lors de la génération de nombres premiers :

//--- outside of our predefined table
   for(int i=(min|1); i<=INT_MAX; i+=2)
     {
      if(IsPrime(i) && ((i-1)%s_hash_prime!=0))
         return(i);
     }
   return(min);

2. La méthode CPrimeGenerator::IsPrime est utilisée pour vérifier le nombre par souci de simplicité.

 

J'ai essayé de passer de mon ArrayList au vôtre, qui est dans Generic/ArrayList.mqh

ME ne donne rien après ".".

Comment obtenir la valeur ? Get() et [] sont absents de la classe.

Et cela ne prend pas en compte le fait qu'il pourrait y avoir un tableau de pointeurs.

Et qui crée cette bibliothèque ?

Voici ma version d'ArrayList de Java :

Dossiers :
ArrayList.mqh  46 kb
 
Il n'y avait pas de modèles de classe lorsque j'ai créé cette variante.
 
Roman Konopelko:

Pour que les collections Generic fonctionnent correctement avec les objets de classe, ces classes doivent implémenter l'interface IEqualityComparable dans laquelle les méthodes Equals et HashCode sont définies. Cela signifie que l'utilisateur doit définir les méthodes de calcul des codes de hachage et c'est la seule option à ce jour, car il est impossible de mettre en œuvre ces méthodes automatiquement, comme cela a été fait dans .Net, par exemple, au moyen de MQL5.

Alors pourquoi votre modèle fonctionne-t-il avec n'importe quel type, trompant le programmeur ? Si seules les classes héritées de IEqualityComparable fonctionnent correctement, alors nous devrions désactiver le travail avec d'autres types au niveau du compilateur.

Laissez-moi vous rappeler ce code :

//+------------------------------------------------------------------+
//| Returns a hashcode for custom object.                            |
//+------------------------------------------------------------------+
template<typename T>
int GetHashCode(T value)
  {
//--- try to convert to equality comparable object  
   IEqualityComparable<T>*equtable=dynamic_cast<IEqualityComparable<T>*>(value);
   if(equtable)
     {
      //--- calculate hash by specied method   
      return equtable.HashCode();
     }
   else
     {
      //--- calculate hash from name of object
      return GetHashCode(typename(value));
     }
  }

Je pense que cette fonction devrait être remplacée par celle-ci :

template<typename  T>
int GetHashCode(IEqualityComparable<T> &value)
  {
    return value.HashCode()
  }
 
Alexey Navoykov:

Si seules les classes héritées de IEqualityComparable fonctionnent correctement, alors vous devriez interdire le travail avec d'autres types au niveau du compilateur.

Il ne sera pas commode de travailler avec ce type. Les surcharges GetHashCode pour les types standard montrent l'interface d'obtention du code de hachage.


Ce qui est ennuyeux, c'est qu'il est absent.

template<typename T>
interface IEqualityComparable
  {
//--- method for determining equality
   bool              Equals(T & value);
//--- method to calculate hash code   
   int               HashCode(void);
  };


C'est-à-dire pour les objets bummer maintenant.

 
fxsaber:

Ce serait gênant de travailler avec ça. Les surcharges GetHashCode pour les types standard montrent l'interface pour obtenir le code de hachage.

Qu'est-ce qui est pratique maintenant ? Le fait de passer un enum ou un pointeur d'une classe qui ne supporte pas l'interface dans cette fonction, vous obtenez juste le nom de la classe ? ) Et le plus important, le code fonctionne et compile comme si tout était normal.

 
Alexey Navoykov:

Qu'est-ce qui est pratique maintenant ? Que passer un enum ou un pointeur d'une classe qui ne supporte pas l'interface dans cette fonction, vous obtenez juste le nom de la classe ? Awesome hash ) Et le plus important, le code fonctionne, compile comme si tout était normal. Ce n'est pas le cas.

Oui, ils ont fait une bêtise. Ils ont inconsidérément copié et collé à partir de NetFramework alors qu'il est évident que sans prise en charge des interfaces au niveau du langage, il ne peut pas fonctionner de manière adéquate. Je me souviens du niveau des codes MQ il y a 6-7 ans et maintenant c'est nul comparé à cette époque.

 
Alexey Navoykov:

Le fait qu'en passant un enum ou un pointeur d'une classe qui ne supporte pas l'interface dans cette fonction, vous obtenez juste le nom de la classe ? Joli hash ) Et le plus important, le code fonctionne et compile comme si tout était ok. Ce n'est pas le cas.

Je suis d'accord, il vaut mieux obtenir une erreur de compilation tout de suite que de s'occuper de la longue question de savoir pourquoi ça ne fonctionne pas.

Pour être honnête, je ne vois même pas pourquoi ils ont collé une interface à cet endroit. Après tout, il suffit de surcharger GetHashCode pour le type requis et non de commencer à créer IEqualityComparable.

Raison: