Errori, bug, domande - pagina 107

 
Yedelkin:
Simpleton, ho seguito la stessa strada, ma ho usato la conversione esplicita al tipo int. Ho supposto che la dimensione massima possibile del lotto sarà limitata o dal broker/dealer, o dalla dimensione dei miei fondi. Quindi usare int dovrebbe essere sufficiente. Pensi che ci siano delle insidie in questo approccio (arrotondare dal basso usando int)?

Per il commercio reale, probabilmente, sì, int/uint è sufficiente.

Ma se si esegue in un tester, potrebbe non essere sufficiente per alcuni esperimenti.

Non ci sono insidie, oltre a possibili glitch successivi nell'implementazione di MQL5, quando si usa int, se possiamo garantire che l'intero N dalla formula cadrà nell'intervallo 0...INT_MAX e quindi non traboccherà. Cioè, sostituire il controllo

tmp < ULONG_MAX * stepvol

a

tmp < INT_MAX * stepvol

In realtà il tipo int è firmato e la metà dei suoi possibili valori si trova nell'area dei numeri negativi, mentre qui saranno sempre non negativi. È irrazionale usare int quando c'è un unsigned uint che ha la stessa dimensione ma il doppio del range nell'area non negativa. Pertanto, se abbiamo intenzione di usare int/uint, è meglio usare uint e sostituire il controllo con uint, rispettivamente:

tmp < UINT_MAX * stepvol
 

gumgum:

#property script_show_inputs

Grazie per il suggerimento.
 
simpleton:

Per il commercio reale, molto probabilmente sì, int/uint è sufficiente.

...In realtà, il tipo int è firmato, la metà dei suoi possibili valori si trova nell'area dei numeri negativi, e qui sarà sempre non negativo. È irrazionale usare int, quando c'è un unsigned uint che ha la stessa dimensione ma il doppio del range nell'area non negativa. Pertanto, se abbiamo intenzione di usare int/uint, è meglio usare uint e sostituire il controllo con uint, rispettivamente:

Sì, ho capito, grazie!
 

Non è un bug, ma un'osservazione interessante sui tipi

Cosa pensi che sia 2 volte 2, cioè 2*2?

pensi 4 forse hai ragione!

OK, che ne dici di questo
duecentomila volte duecentomila

200000 * 200000

Qualsiasi scolaro può moltiplicare i due e i quattro e aggiungere gli zeri e ottenere...

40000000000.

Ora scriviamo un semplice codice nel linguaggio della macchina.

lotti lunghi = 200000*200000;

notate che il tipo di host della variabile è lungo, cioè
Il valore minimo è -9 223 372 036 854 775 808; il valore massimo è 9 223 372 036 854 775 807.

Stampa il totale e ottieni

lotti = 1345294336
che è molto diverso da due volte due e otterrete due.

Ho riletto la sezione di aiuto sui tipi e le conversioni di tipo.
Non ho trovato alcuna informazione che i numeri regolari devono essere esplicitamente castati al tipo giusto

quindi è così che dovrebbe essere

lotti lunghi = (lungo) 200000 * (lungo) 200000;

In alternativa, è possibile utilizzare ulteriori variabili ausiliarie.

Документация по MQL5: Основы языка / Типы данных / Приведение типов
Документация по MQL5: Основы языка / Типы данных / Приведение типов
  • www.mql5.com
Основы языка / Типы данных / Приведение типов - Документация по MQL5
 

C'è di più.

Se volete recuperare e moltiplicare per grandi numeri alcune proprietà....

Ecco il codice

long A = AccountInfoInteger(ACCOUNT_LOGIN);  // 661701
long B = A;
long C = 661701;
Print(" A=",A,"  B=",B,"  C=",C);
long X =10000;

long L1 = A*X;
long L2 = B*X;
long L3 = C*X;

Print(" L1=",L1,"   L2=",L2,"   L3=",L3);

Ed ecco il risultato

L1=2322042704   L2=2322042704   L3=6617010000
A =661701        B =661701      C =661701
gli input sono gli stessi, ma il risultato è diverso
File:
servis.mq5  2 kb
 

SHOOTER777:

E ora un semplice codice in linguaggio macchina

lotti lunghi = 200000*200000;

Notate che il tipo ricevente della variabile long è long, cioè
Il valore minimo è -9 223 372 036 854 775 808, il valore massimo è 9 223 372 036 854 775 807.

Stampa il totale e ottieni

lotti = 1345294336
che è molto diverso da due volte due e otterrete due.

Ho riletto la sezione di aiuto sui tipi e le conversioni di tipo.
Non ho trovato alcuna informazione sul fatto che si debbano castare esplicitamente i numeri regolari in un certo tipo.

quindi è così che dovrebbe essere

lotti lunghi = (lungo) 200000 * (lungo) 200000;

In alternativa, potete anche usare variabili ausiliarie.

I "numeri ordinari" sono espressioni costanti che hanno anche un tipo. In questo caso, è il tipo int.

L'espressione che consiste nella moltiplicazione di due sottoespressioni, ciascuna delle quali è di tipo int, è anch'essa di tipo int. È qui che si verifica l'overflow.

E solo allora la conversione implicita dal tipo dell'espressione int al tipo long avviene durante l'inizializzazione della variabile di tipo long.

Qui tutto è chiaro. A proposito, ciascuno degli operandi in questo caso non ha bisogno di essere castato al tipo lungo. È sufficiente lanciarne uno, e il secondo sarà lanciato implicitamente.

 
SHOOTER777:

C'è di più.

Se volete recuperare e moltiplicare per grandi numeri alcune proprietà....

Ecco il codice

Ed ecco il risultato.

I dati di partenza sono gli stessi, ma il risultato è diverso.

Sembra che il registro e il codice siano confusi. Il codice di cui sopra funziona "pulito". E, per ottenere un tale registro, ho dovuto rendere le variabili A e B di tipo int o uint, e la variabile X di tipo uint:

void OnStart()
{
int A = 661701;
int B = A;
long C = 661701;
Print(" A=",A,"  B=",B,"  C=",C);
uint X =10000;

long L1 = A*X;
long L2 = B*X;
long L3 = C*X;

Print(" L1=",L1,"   L2=",L2,"   L3=",L3);
}

/* Вывод в лог (хронология - сверху вниз):
KO      0       1 (EURUSD,M15)  00:46:28         A=661701  B=661701  C=661701
OE      0       1 (EURUSD,M15)  00:46:28         L1=2322042704   L2=2322042704   L3=6617010000
*/

Ed ecco come funziona il codice originale:

void OnStart()
{
long A = 661701;
long B = A;
long C = 661701;
Print(" A=",A,"  B=",B,"  C=",C);
long X =10000;

long L1 = A*X;
long L2 = B*X;
long L3 = C*X;

Print(" L1=",L1,"   L2=",L2,"   L3=",L3);
}

/* Вывод в лог (хронология сверху вниз):
DL      0       1 (EURUSD,M15)  00:49:13         A=661701  B=661701  C=661701
HG      0       1 (EURUSD,M15)  00:49:13         L1=6617010000   L2=6617010000   L3=6617010000
*/

Build 314 (20 agosto 2010).

Документация по MQL5: Основы языка / Типы данных / Целые типы / Типы char, short, int и long
Документация по MQL5: Основы языка / Типы данных / Целые типы / Типы char, short, int и long
  • www.mql5.com
Основы языка / Типы данных / Целые типы / Типы char, short, int и long - Документация по MQL5
 

Potete dirmi, per esempio, se voglio ottenere il valore di qualche indicatore. Lo ottenevo esattamente e con certezza usando la funzione built-in. Ora devo scriverlo da solo usando un mucchio di codice, buffer, handle, ecc. Ma non è questo il punto. La cosa principale per me è che il codice diventa glitch letteralmente su ogni linea, perché devo controllare ogni linea di codice per assicurarmi che non si sia verificato alcun errore... In generale, pensavo che tutte queste complessità, classi e cose che erano elementari ma che diventavano ingombranti e scomode fossero fatte per aumentare la velocità, l'affidabilità, ecc. Ho letto un articolo su 20 segnali... c'è scritto:

"Non potete accedere ai dati dell'indicatore subito dopo la sua creazione, poiché ci vuole un po' di tempo per calcolare i valori dell'indicatore, quindi è meglio creare gli handle dell'indicatore in OnInit()".

Poi ci sono controlli per ogni linea

"Controlliamoli: se ci sono meno dati di quelli di cui abbiamo bisogno, significa che si è verificato un errore di copia e un ulteriore accesso all'array, dove i dati dovrebbero essere memorizzati, porterà a un errore. Per escludere questo, abbandoneremo la funzione".

Così, invece di accelerare, devo fare un ciclo (quante volte?) attraverso questa funzione per ottenere un risultato alla fine... E se ho bisogno di valori individuali di linee separate di indicatori diversi periodicamente... Questa è una funzione separata per ogni valore... Sono un sacco di variabili e codice extra...

Insomma, spiegatemi, datemi un link, voglio capire il senso di tutto questo, perché è così e non così affidabile...

E sarebbe bene che le risposte a tali domande potessero essere messe nella sezione di aiuto alla migrazione da µl4 a µl5 o creare una sezione apposita sul forum, senza alcuna discussione, in particolare una domanda e risposta, con una spiegazione del perché è così... per esempio, il periodo è spiegato qui in modo molto accessibile, e allo stesso modo vorremmo avere risposte a domande elementari

 
Dmitriy2:

Potete dirmi, per esempio, se voglio ottenere il valore di qualche indicatore. Lo ottenevo esattamente e con certezza usando la funzione built-in. Ora devo scriverlo da solo usando un mucchio di codice, buffer, handle, ecc. Ma non è questo il punto. La cosa principale per me è che il codice diventa glitch letteralmente su ogni linea, perché devo controllare ogni linea di codice per assicurarmi che non si sia verificato alcun errore... In generale, pensavo che tutte queste complessità, classi e cose che erano elementari ma che diventavano ingombranti e scomode fossero fatte per aumentare la velocità, l'affidabilità, ecc. Ho letto un articolo su 20 segnali... c'è scritto:

"Non potete accedere ai dati dell'indicatore subito dopo la sua creazione, poiché ci vuole un po' di tempo per calcolare i valori dell'indicatore, quindi è meglio creare gli handle dell'indicatore in OnInit()".

Poi ci sono controlli per ogni linea

"Controlliamoli: se ci sono meno dati di quelli di cui abbiamo bisogno, significa che si è verificato un errore di copia e un ulteriore accesso all'array, dove i dati dovrebbero essere memorizzati, porterà a un errore. Per escludere questo, abbandoneremo la funzione".

Così, invece di accelerare, devo fare un ciclo (quante volte?) attraverso questa funzione per ottenere un risultato alla fine... E se ho bisogno di valori individuali di linee separate di indicatori diversi periodicamente... Questa è una funzione separata per ogni valore... Sono un sacco di variabili e codice extra...

Insomma, spiegatemi, datemi un link, voglio capire il senso di tutto questo, perché è così e non così affidabile...

E sarebbe bene che le risposte a tali domande potessero essere messe nella sezione di aiuto alla migrazione da µl4 a µl5 o creare una sezione apposita sul forum, senza alcuna discussione, nello specifico una domanda e risposta, con una spiegazione del perché è così... per esempio, il periodo è spiegato qui in un modo molto accessibile, quindi sarebbe bene avere risposte a domande elementari nello stesso modo

È più affidabile? Perché è inaffidabile ottenere gli handle all'inizializzazione? Perché non è affidabile controllare la disponibilità dei dati richiesti? E inoltre, perché non è affidabile avere dei controlli?

Potrebbe non essere così facile per i principianti, ma con il tempo diventerà chiaro...

 
Interesting:

Più affidabile? Perché ottenere gli handle all'inizializzazione non è affidabile? Perché è inaffidabile controllare i dati necessari? E ancora di più, perché avere dei controlli non è affidabile?

Potrebbe non essere così semplice per i neofiti, ma diventerà chiaro col tempo...

Il controllo dei dati non degrada la velocità del programma nel suo complesso, forse solo dello 0,01%, non ho fatto questo controllo, e il fatto che i dati debbano essere controllati prima di usarli è solo per la stabilità dell'intero sistema, altrimenti ci possono essere conseguenze imprevedibili, fino al crash del terminale nel suo complesso.