Biblioteca de classes genéricas - bugs, descrição, perguntas, recursos de uso e sugestões - página 20

 
Sergey Dzyublik:

1. Eliminar comportamentos ambíguos:
Se passarmos "INT_MAX - 10" como parâmetro ao CPrimeGenerator::ExpandPrime, o resultado "INT_MAX" será devolvido.
Se passarmos "INT_MAX - 10" como parâmetro ao CPrimeGenerator::GetPrime, o mesmo resultado será devolvido: "INT_MAX - 10".

Em ambos os casos, o valor retornado não é um número primo que induza o usuário em erro.

Sobre o primeiro ponto:

Não há nenhuma ambiguidade aqui.

O método GetPrime deve retornar o número prime mais próximo de cima, mas no intervalo de INT_MAX - 10 a INT_MAX não há nenhum, por isso INT_MAX - 10 é retornado.

O método ExpandPrime primeiro duplica o valor de entrada e o método GetPrime é chamado a partir do número recebido.

Além disso, o ExpandPrime tem um cheque para INT_MAX overrun:

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

Na minha opinião, a lógica por detrás do comportamento destes métodos é absolutamente inequívoca e correcta.


Em relação ao segundo e terceiro itens:

As alterações que você sugere só são relevantes para a maioria dos problemas de borda, quando os tamanhos do CHashMap são muito grandes. No entanto, não há garantias de que elas terão um impacto positivo no desempenho, portanto, estudos separados precisam ser feitos para determinar a correção das mudanças que você sugere.

 
Roman Konopelko:

Não há nenhuma ambiguidade aqui.
O método GetPrime deve retornar o número prime mais próximo de cima, mas não há nenhum entre INT_MAX - 10 e INT_MAX, então INT_MAX - 10 é retornado.
O método ExpandPrime primeiro duplica o valor de entrada e o método GetPrime é chamado a partir do número recebido.
Além disso, o ExpandPrime tem um cheque para INT_MAX overrun:
A lógica do comportamento destes métodos é absolutamente inequívoca e correta.


1. As funções podem retornar números desconhecidos em vez de números primos.
Como um usuário usa esses dados é problema dele, talvez ele os jogue no longo prazo e os passe para as funções de supercomputação, que se importa.
O fato é que podemos devolver algo diferente do que é declarado e esperado das funções por padrão.

2. Como podemos verificar se a chamada de função retornou um número primo e não algo mais?
Não se pode simplesmente compará-lo com o INT_MAX.
Você deve compará-lo com o último número primo disponível a menos do que INT_MAX.
Cada vez que se compara o resultado das chamadas destas funções com algum número mágico para ter certeza de que tudo está bem, eu acho absurdo.

 
Sergey Dzyublik:

1. As funções podem não retornar números primos, mas números obscuros.
A forma como o usuário usa esses dados é problema dele, talvez ele os jogue em longo prazo e depois os passe para funções de supercomputação, quem se importa.
O fato é que podemos devolver algo diferente do que é declarado e esperado das funções por padrão.

2. Como podemos verificar se a chamada de função retornou um número primo e não algo mais?
Não se pode simplesmente compará-lo com o INT_MAX.
Você deve compará-lo com o último número primo disponível a menos do que INT_MAX.
Comparar o resultado de cada chamada destas funções com algum número mágico cada vez para ter certeza de que tudo está correto, me parece absurdo.

1. Seu caso de obter um número não simples usando o método GetPrime é o único que eu encontrei até agora. Este incidente será corrigido através da alteração do cheque ao gerar números primos:

//--- 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. O CPrimeGenerator::Método IsPrime é usado para verificar o número para simplificar

 

Tentei mudar da minha ArrayList para a sua, que está em Generic/ArrayList.mqh

ME não dá nada depois de ".".

Como é que eu consigo o valor? Faltam() e [] na aula.

E não leva em conta que pode haver uma série de indicadores.

E quem cria esta biblioteca?

Aqui está a minha versão do ArrayList de Java:

Arquivos anexados:
ArrayList.mqh  46 kb
 
Não havia modelos de classe quando eu criei esta variante.
 
Roman Konopelko:

Para que coleções genéricas funcionem corretamente com objetos de classe, estas classes devem implementar a interface IEqualityComparable na qual os métodos Equals e HashCode são definidos. Isso significa que o usuário tem que definir métodos de cálculo de códigos hash e essa é a única opção até agora, pois é impossível implementar esses métodos automaticamente, como foi feito em .Net, por exemplo, por meio de MQL5.

Então porque é que o seu template funciona com qualquer tipo, enganando o programador? Se apenas as classes herdadas do IEqualityComparable funcionam correctamente, então devemos desactivar o trabalho com outros tipos ao nível do compilador.

Deixa-me lembrar-te deste código:

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

Eu acredito que esta função deve ser substituída por esta:

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

Então porque é que o seu template funciona com qualquer tipo, enganando o programador? Se apenas as classes herdadas do IEqualityComparable funcionam correctamente, então você deve proibir o trabalho com outros tipos a nível de compilador.

Será inconveniente trabalhar com este tipo de trabalho. As sobrecargas do GetHashCode para os tipos padrão mostram a interface de obtenção de código hash.


O que é irritante é que está ausente.

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


Isto é, para os objectos, agora é uma chatice.

 
fxsaber:

Isto seria embaraçoso de se trabalhar. As sobrecargas do GetHashCode para tipos padrão mostram a interface para obter o código hash.

E o que é conveniente agora? O fato de passar um enumero ou ponteiro de uma classe que não suporta a interface para esta função, você apenas recebe o nome da classe? ) E o mais importante, o código funciona e compila como se tudo estivesse normal.

 
Alexey Navoykov:

Qual é a conveniência agora? Que ao passar um enumero ou ponteiro de uma classe que não suporta a interface para esta função, você apenas recebe o nome da classe? Um hash incrível ) E o mais importante, o código funciona, compila como se tudo estivesse normal. Este não é o caso.

Sim, eles fizeram uma porcaria. Eles copiaram e colaram sem pensar a partir do NetFramework enquanto é óbvio que sem suporte para interfaces a nível linguístico não pode funcionar adequadamente. Lembro-me do nível dos códigos MQ há 6-7 anos e agora é uma porcaria em comparação com aquela época.

 
Alexey Navoykov:

Qual é a conveniência agora? O fato de passar um enumero ou ponteiro de uma classe que não suporta a interface para esta função, você apenas recebe o nome da classe? Belo hash ) E o mais importante, o código funciona e compila como se tudo estivesse bem. Este não é o caso.

Concordo, é melhor obter um erro de compilação imediatamente do que lidar com a longa questão do porquê de não funcionar.

Para ser honesto, nem vejo porque é que eles enfiaram lá uma interface. Afinal, você só precisa sobrecarregar o GetHashCode para o tipo necessário e não começar a criar o IEqualityComparable.

Razão: