Implementações alternativas de funções/abordagens padrão - página 9

 
fxsaber:

Chegamos ao ponto em que o problema não ocorre mais e o esquecemos com segurança. É ótimo quando você não precisa voltar a um código uma vez escrito. Funciona - isso é o principal.

É isso mesmo. Eu mesmo sempre faço isto (e desta vez também, como você pode ver).

O problema surgirá se algo mudar de repente. Quando o código é claro e lugares não óbvios são bem comentados, as causas de erros em algumas mudanças são fáceis de encontrar. Mas em tais casos de "e esqueceu" - é muito mais difícil fazer correções.

Sim, é claro, que é um caso raro... Mas estes casos muito raros - pessoalmente, estou muito nervoso. É por isso que em tais situações eu tento escrever códigos claros o máximo possível e dar comentários detalhados para lugares não óbvios.

 
fxsaber:

Um exemplo do meu código, que neste momento não entendo de forma alguma. E há muitos fatores que precisam ser muito bem compreendidos.


Como você pode ver, o código/estilo é muito simples. Mas só serei capaz de detectar um erro nele ou em sua ausência quando for capaz de escrever o mesmo código novamente. Realmente vou levar muito tempo, pois preciso entrar completamente no problema.

É por isso que o princípio é que as coisas complexas são limpas (os testes de estresse são escritos) na fase de criação e utilizadas de forma simples através da conexão de mqh. Como você pode ver, a complexidade nem sempre é determinada pelo estilo ou pela brevidade.


Há também um exemplo de construções puramente lingüísticas - TypeToBytes. A complexidade de compreensão é um nível bem diferente. E aqui é onde eu murcharia sem macros. É por causa das macros que você entra no código fonte muito rapidamente. Porque as macros são freqüentemente usadas não para a brevidade, mas para a compreensão.


E há também o caso quando você tem que considerar muitas armadilhas descomplicadas, mas esquecíveis. Este é o caso do MT4Orders. É por isso que algumas linhas lá são acompanhadas de comentários dirigidos apenas a si mesmo. Ajuda a entender seu código.


Mas note que todos estes são mqh, nos quais você não precisa entrar. E o código da TC é escrito com mqh, o que é muito simples. Não se investiga o código fonte das funções iHigh regulares. E eles são realmente monstros. Basta usá-los. Você deve fazer o mesmo com as bibliotecas. A mesma Bíblia Genérica a ser usada não requer que você a entenda totalmente.


Veja o QB para MT4 EAs e seus portos MT5. Os portos do MT5 são um covarde para entender. Não só não cheira perto da concisão (o código é muitas vezes maior do que o original), mas também tem armadilhas MT5 que não são contabilizadas nos arquivos de mqh.

Honestamente, não tenho nada com que discutir aqui. Obviamente, tudo está correto com base em sua abordagem da programação (talvez apenas com exceção dos casos de compressão excessiva e injustificada do código), mas se você adotar minha abordagem, muita coisa está errada.

1. é claro, erros difíceis de encontrar podem se esconder mesmo em código muito simples de escrever. Mas eles são ainda mais difíceis de encontrar em código difícil de escrever. Considere o esforço mental envolvido em desembrulhar o significado. Se você precisa fazer um grande volume de trabalho (escrever muitas funções, construir novos mecanismos, integrá-los com sucesso aos já existentes), economizar tempo e esforço é o principal. Não se trata de "beleza" do código. Não sobre estilos. Você precisa compor seu código de tal forma que possa lê-lo no meio da noite e entendê-lo o mais rápido possível. Você começa a procurar o método ideal de codificação a fim de obter o máximo resultado de si mesmo. E olhando para ela:

return((int)((Value > 0) ? Value / Points[digits] + HALF_PLUS : Value / Points[digits] - HALF_PLUS) * Points[digits]);

você compreende imediatamente todas as desvantagens de escrevê-lo desta maneira:

1. Muitos personagens.

2. Excessiva "embalagem".

3. operações matemáticas não comentadas.

Você não será capaz de lidar com este código enquanto estiver acordado. Também é difícil lidar com o excesso de trabalho e o cansaço. Imagine que você está trabalhando assim todos os dias. Você imediatamente se afasta de tal código.


2. Não olhe para o código dos outros e simplesmente conecte-o?

Acredito que programas grandes, sérios e, o que é mais importante, de alta qualidade não são criados apenas pela montagem de blocos de outras pessoas. Não se pode criar um programa eficiente criando apenas uma pequena parte dele e anexando o resto. Será uma "bagunça".

Ela pode e vai funcionar. Mas estes são programas "improvisados".

Não acredito na eficácia de programas montados a partir de blocos (nos quais o desenvolvedor nem sequer olha). Isto é uma ficção. O programa será coxo e as soluções serão ineficazes. Haverá uma série de problemas. Se os programadores trabalham em equipe e resolvem uma tarefa comum, é bom, mas se são usadas soluções que "flutuam" entre diferentes programas de pessoas diferentes (que nem sequer olham para elas), não é nada do ponto de vista da eficiência.

 
Реter Konow:

Ela pode e vai funcionar. Mas isto é, - programas "de joelhos".

Você pode consultar minhas publicações na KB. Alguém deve estar usando-as.

Escrevo somente para mim mesmo e "de joelhos". As publicações são um subproduto.

 
Georgiy Merts:

Portanto, a verificação para LONG_MAX - deve ser antes de converter o dobro para longo. Claramente, a função de arredondamento não é projetada para valores que não cabem em um número inteiro. E isso não muda o problema.

Se a função retorna o dobro, que depois convertemos em longo, enfrentamos o mesmo perigo de transbordamento.

Pessoalmente, sempre fiz a verificação de valores-limite pouco antes do arredondamento; além disso, a lógica do programa é que eu sempre me asseguro de que um valor maior que o máximo para um número inteiro nunca possa chegar à transformação.

Você costuma se lançar por muito tempo no charuto? É o mesmo com o dobro - é o último degrau da hierarquia, você não precisa lançá-lo, na maioria dos casos você não precisa, std tem tudo para trabalhar com ele. Não jogue a hierarquia abaixo e não se preocupe com isso.

Acrescente verificações no LONG_MAX/MIN - e algo me diz que os testes de desempenho não serão tão cor-de-rosa. E a pessoa tem como objetivo a substituição std, portanto deve trabalhar para toda a gama de valores.

 
pavlick_:

Você joga muito tempo no charuto frequentemente? É o mesmo com a dabl - é o último degrau da hierarquia, não há necessidade de se lançar dela, na maioria dos casos não há nada a ver com ela, a std tem tudo para trabalhar com ela. Não abaixe a hierarquia e não se preocupe.

Adicione cheques para LONG_MAX/MIN e tenho certeza de que os testes de desempenho não terão tanta sorte. E o homem tem como objetivo a substituição std, portanto deve trabalhar para toda a gama de valores.

longo a ulong (e vice versa) - com muita freqüência.

longo a char - raramente.

A conversão é necessária porque operações inteiras e de ponto flutuante resultam significativamente diferentes. A velocidade de execução dos dados inteiros também é supostamente mais rápida.

Sobre a verificação de alcance - já enfatizei que é ASSERT - ou seja, tal verificação só funciona em DEBUG-versão. No meu caso, todos os parâmetros de entrada são sempre verificados para uma faixa válida com afirmações no início de qualquer função pública, o que me ajudou mais de uma vez. As versões RELEASE, é claro, já funcionam sem nenhuma verificação.

 
fxsaber:

Você pode dar uma olhada em minhas publicações na KB. Alguém deve estar usando-as.

Eu só escrevo para mim mesmo e "de joelhos". As publicações são um subproduto.

Não estou questionando sua experiência e profissionalismo.

É só que no processo de programação e desenvolvimento exaustivo e diário durante vários anos você começa a estimar as vantagens de algum código, solução ou abordagem específica. E muitas vezes chegam a conclusões muito estranhas... Estranhas, mas justificadas por muita prática.

Estou apenas compartilhando meu ponto de vista.

 
Georgiy Merts:

A necessidade de conversão surge porque o resultado de operações inteiras e de ponto flutuante é significativamente diferente.

Não consigo imaginar em que situações algo não pode ser feito corretamente com rublos. Em Lua (anexado ao quik), não há nenhum tipo inteiro, apenas rublos, e nada.

 
pavlick_:

Tenho uma má idéia em que situações algo não pode ser feito adequadamente em casos de problemas.

Contador.

void OnStart()
{
  const long Num1 = 9007199254967295;
  const long Num2 = Num1 + 1;

  Print(Num1 == Num2); // false
  Print((double)Num1 == (double)Num2); // true
}

odobro não perde todas as informações de alcance, não tanto com o longo prazo.

Особенности языка mql5, тонкости и приёмы работы
Особенности языка mql5, тонкости и приёмы работы
  • 2018.01.15
  • www.mql5.com
В данной теме будут обсуждаться недокументированные приёмы работы с языком mql5, примеры решения тех, или иных задач...
 
fxsaber:

Contador.

Bem, você ainda tem que contar até tantos )). E se você realmente quiser, isso não é uma opção:

double cnt;
double high_cnt;
if (++ cnt == 1 000 000) {
   ++ high_cnt;
   cnt = 0;
}
 
pavlick_:

Bem, você ainda tem que contar até tantos )). Mas se você realmente quiser, isso não é uma opção:

É compreensível que seja possível ficar distorcido. Mas será que vale a pena?

Na minha opinião, se a variável deve ter apenas valores inteiros, ela deve ser inteira apenas para tornar impossível escrever um valor de ponto flutuante nela. O tipo de variável ou valor de retorno em si já contém informações importantes sobre a variável e parcialmente sobre o algoritmo. Se usarmos valores de ponto flutuante em todos os lugares, esta informação será perdida.

E mesmo o inteiro - dependendo do algoritmo, em minha opinião - deve ser declarado como assinado ou não, e não necessariamente longo, mas talvez "mais curto" - apenas para que ao olharmos para o código possamos entender imediatamente que faixa de valores a variável em questão pode ter.

O fato de não haver valores inteiros em Lua é, em minha opinião, uma séria desvantagem.