Implementazioni alternative di funzioni/approcci standard - pagina 9

 
fxsaber:

Sono arrivato al punto in cui il problema non si verifica più e me ne sono tranquillamente dimenticato. È fantastico quando non si deve tornare al codice scritto una volta. Funziona - questa è la cosa principale.

Proprio così. Lo faccio sempre io (e anche questa volta, come potete vedere).

Il problema sorgerà se qualcosa cambia improvvisamente. Quando il codice è chiaro e i luoghi non ovvi sono ben commentati, le cause degli errori in alcune modifiche sono facili da trovare. Ma in questi casi di "e dimenticato" - è molto più difficile fare correzioni.

Sì, certo, che è un caso raro... Ma questi casi molto rari - personalmente sono molto nervoso. Ecco perché in queste situazioni cerco di scrivere del codice che sia il più chiaro possibile e di commentare il più possibile i punti non ovvi.

 
fxsaber:

Un esempio del mio codice, che in questo momento non capisco affatto. E ci sono molti fattori che devono essere compresi molto bene.


Come potete vedere, il codice/stile è molto semplice. Ma sarò in grado di rilevare un errore in esso o la sua assenza solo quando sarò in grado di scrivere di nuovo lo stesso codice. Mi ci vorrà davvero molto tempo, perché ho bisogno di entrare completamente nel problema.

Ecco perché il principio è che le cose complesse vengono ripulite (vengono scritti gli stress test) in fase di creazione e utilizzate in forma semplice inserendo mqh. Come potete vedere, la complessità non è sempre determinata dallo stile o dalla brevità.


C'è anche un esempio di costrutti puramente linguistici - TypeToBytes. La complessità della comprensione è di un altro livello. Ed è qui che appassirei senza macro. È grazie alle macro che si entra abbastanza rapidamente nel codice sorgente. Perché le macro sono spesso usate non per la brevità, ma per la comprensione.


E c'è anche il caso in cui bisogna considerare un sacco di insidie non complicate ma dimenticabili. Questo è il caso di MT4Orders. Ecco perché alcune righe sono accompagnate da commenti rivolti solo a se stessi. Aiuta a capire il tuo codice.


Ma si noti che questi sono tutti mqh, che non è necessario entrare. E il codice di TC è scritto con mqh, che è molto semplice. Non si guarda nel codice sorgente delle funzioni regolari di iHigh. E sono davvero dei mostri. Basta usarli. Dovreste fare lo stesso con le biblioteche. La stessa Bibbia generica da usare non richiede che la comprendiate appieno.


Guarda il QB per gli EA MT4 e le loro porte MT5. Le porte di MT5 sono uno strazio da capire. Non solo non sa di concisione (il codice è molte volte più grande dell'originale), ma è anche pieno di tranelli di MT5 che non sono considerati nei file mqh.

Onestamente, non ho niente da discutere qui. Ovviamente, tutto è corretto in base al tuo approccio alla programmazione (forse solo con l'eccezione dei casi di eccessiva e ingiustificata compressione del codice), ma se prendi il mio approccio, molte cose sono sbagliate.

1. naturalmente, errori difficili da trovare possono nascondersi anche in un codice scritto molto semplicemente. Ma sono ancora più difficili da trovare nel codice difficile da scrivere. Considera lo sforzo mentale che comporta lo spacchettamento del significato. Se avete bisogno di fare una grande quantità di lavoro (scrivere molte funzioni, costruire nuovi meccanismi, integrarli con successo in quelli esistenti), risparmiare tempo e fatica è la cosa principale. Non si tratta di "bellezza" del codice. Non si tratta di stili. Dovete comporre il vostro codice in modo tale da poterlo leggere nel mezzo della notte e capirlo il più rapidamente possibile. Si inizia a cercare il metodo ideale di codifica per ottenere il massimo risultato da se stessi. E guardarlo:

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

si capiscono immediatamente tutti gli svantaggi di scriverlo in questo modo:

1. Un sacco di personaggi.

2. Eccessivo "imballaggio".

3. operazioni matematiche non commentate.

Non sarete in grado di gestire questo codice mentre siete svegli. È anche difficile far fronte all'eccesso di lavoro e alla stanchezza. Immaginate di lavorare così ogni giorno. Ci si allontana immediatamente da un tale codice.


2. Non guardare il codice degli altri e inserirlo semplicemente?

Credo che i programmi grandi, seri e, ciò che è più importante, di alta qualità non si creano semplicemente assemblando i blocchi di altre persone. Non si può creare un programma efficiente creando solo una piccola parte di esso e attaccando il resto. Sarà un "casino".

Può funzionare e funzionerà. Ma questi sono programmi "improvvisati".

Non credo nell'efficacia dei programmi assemblati da blocchi (in cui lo sviluppatore non guarda nemmeno). Questa è una finzione. Il programma sarà zoppo e le soluzioni saranno inefficaci. Ci saranno molti problemi. Se i programmatori lavorano in squadra e risolvono un compito comune, va bene, ma se si usano soluzioni che "galleggiano" tra diversi programmi di persone diverse (che non le guardano nemmeno), non è niente dal punto di vista dell'efficienza.

 
Реter Konow:

Può funzionare e funzionerà. Ma questo è, - programmi "in ginocchio".

Potete guardare le mie pubblicazioni in KB. Qualcuno deve usarli.

Scrivo solo per me stesso e "in ginocchio". Le pubblicazioni sono un sottoprodotto.

 
Georgiy Merts:

Quindi il controllo per LONG_MAX - dovrebbe essere prima di convertire il doppio in lungo. Chiaramente, la funzione di arrotondamento non è progettata per valori che non rientrano in un intero. E non cambia il problema.

Se la funzione restituisce double, che poi convertiamo in long, affrontiamo lo stesso pericolo di overflow.

Personalmente, ho sempre un assert-checking per i valori limite appena prima dell'arrotondamento; inoltre, la logica del programma è che mi assicuro sempre che un valore maggiore del massimo per un intero non possa mai arrivare alla trasformazione.

Lancia spesso lungo nel salmerino? È lo stesso con double - è l'ultimo gradino della gerarchia, non c'è bisogno di castarlo, nella maggior parte dei casi non è necessario, std ha tutto per lavorare con esso. Non gettare a terra la gerarchia e non preoccuparti.

Aggiungete controlli su LONG_MAX/MIN - e qualcosa mi dice che i test di performance non saranno così rosei. E la persona mira alla sostituzione std, quindi dovrebbe funzionare per tutta la gamma di valori.

 
pavlick_:

Lanciate spesso long in char? È lo stesso con dabl - è l'ultimo gradino della gerarchia, non c'è bisogno di lanciare da esso, nella maggior parte dei casi non c'è niente da fare con esso, std ha tutto per lavorarci. Non gettare giù la gerarchia e non disturbare.

Aggiungete i controlli per LONG_MAX/MIN e sono sicuro che i test di performance non saranno così fortunati. E l'uomo punta alla sostituzione std, quindi dovrebbe funzionare per tutta la gamma di valori.

lungo a ulong (e viceversa) - troppo spesso.

lungo a char - raramente.

La conversione è necessaria perché le operazioni intere e in virgola mobile risultano significativamente diverse. Anche la velocità di esecuzione dei dati interi è presumibilmente più veloce.

Riguardo al controllo dell'intervallo - ho già sottolineato che è ASSERT - cioè tale controllo funziona solo nella versione DEBUG. Nel mio caso tutti i parametri di input sono sempre controllati per un range valido con asserti all'inizio di ogni funzione pubblica, il che mi ha aiutato più di una volta. Le versioni RELEASE, ovviamente, funzionano già senza alcun controllo.

 
fxsaber:

Potete dare un'occhiata alle mie pubblicazioni in KB. Qualcuno deve usarli.

Scrivo solo per me stesso e "in ginocchio". Le pubblicazioni sono un sottoprodotto.

Non sto mettendo in dubbio la sua esperienza e professionalità.

È solo che nel processo di programmazione e sviluppo estenuante e quotidiano durante diversi anni si inizia a stimare i vantaggi di qualche particolare codice, soluzione o approccio. E spesso si arriva a conclusioni molto strane... Strani ma giustificati da molta pratica.

Sto solo condividendo il mio punto di vista.

 
Georgiy Merts:

La necessità di una conversione nasce dal fatto che il risultato delle operazioni intere e in virgola mobile è significativamente diverso.

Non riesco a immaginare in quali situazioni qualcosa non possa essere fatto correttamente con i dubles. In Lua (allegato a quik), non ci sono tipi interi, solo duble, e niente.

 
pavlick_:

Ho una cattiva idea in quali situazioni qualcosa non può essere fatto correttamente sui dubles.

Contatore.

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

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

Ildoppio non perde tutte le informazioni int-range, non più così a lungo.

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

Contatore.

Beh, devi ancora contare fino a quel numero )). E se lo vuoi davvero, non è un'opzione:

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

Beh, devi ancora contare fino a quel numero )). Ma se lo vuoi davvero, non è un'opzione:

È comprensibile che ci si possa attorcigliare. Ma ne vale la pena?

Secondo me, se la variabile deve avere solo valori interi - deve essere intera solo per rendere impossibile scriverci un valore in virgola mobile. Il tipo di variabile o valore di ritorno stesso contiene già informazioni importanti sulla variabile e parzialmente sull'algoritmo. Se usiamo valori in virgola mobile ovunque, questa informazione andrà persa.

E anche l'intero - a seconda dell'algoritmo, secondo me - deve essere dichiarato come firmato o non firmato, e non necessariamente lungo, ma forse "più corto" - proprio in modo che quando si guarda il codice si può immediatamente capire quale gamma di valori la variabile in questione può avere.

Il fatto che non ci siano valori interi in Lua è, secondo me, un grave svantaggio.