Se è per il confronto, allora si potrebbe facilmente creare la propria funzione:
bool checkDoubles(double a, double b, string check)
{
if(check==">"){
if (a - b > Point / 2)return(1);elsereturn (0);
}elseif(check=="<"){
if (b - a > Point / 2)return(1);elsereturn (0);
}elseif(check==">="){
if (a - b > -Point)return(1);elsereturn (0);
}if(check=="<="){
if (b - a > -Point)return(1);elsereturn (0);
}elseif(check=="!="){
if (MathAbs(a - b) > Point / 2)return(1);elsereturn (0);
}else {
Print("Sorry you've entered a wrong check value");
}
return (0);
}
L'uso di "Point" o "Point/2.0" non è un valore di differenza molto buono, IMO. L'errore di arrotondamento introdotto da NormalizeDouble (che mi ha bruciato oggi), è certamente molto più piccolo di 8 cifre, più probabilmente 15 cifre.
Visti i suggerimenti precedenti, ho apportato alcune modifiche e messo insieme la seguente routine che sembra funzionare bene (anche usando il "diff" a 15 cifre decimali), anche se non è stata ancora testata rigorosamente:
//+------------------------------------------------------------------+bool AvsB(double A, string checkStr, double B)
{
//checkStr = StringTrimLeft(StringTrimRight(checkStr));
double diff = 0.000000000000001; // 15 decimal places//double diff = 0.000000005;//double diff = 0.00000001;if (checkStr == ">" ){if (A - B > diff)return(true);elsereturn(false);}
elseif(checkStr == "<" ){if (B - A > diff)return(true);elsereturn(false);}
elseif(checkStr == ">="){if (A - B > -diff)return(true);elsereturn(false);}
elseif(checkStr == "<="){if (B - A > -diff)return(true);elsereturn(false);}
elseif(checkStr == "!="){if (MathAbs(A - B) > diff)return(true);elsereturn(false);}
elseif(checkStr == "=" || checkStr == "=="){if (MathAbs(A - B) < diff)return(true);elsereturn(false);}
else {Print("Sorry, bad usage: AvsB(A, checkStr, B). Wrong checkStr value: ",checkStr);}
return(false);
} // end of AvsB//+------------------------------------------------------------------+
Here is a check of the obvious:
if (1.34929 == NormalizeDouble(1.34929 , 5)) Alert("MT4 Pass");
elseAlert("MT4 FAIL. ROUNDOFF BUG"); // Yes, this is what MT4 does, a fail.if (AvsB(1.34929 ,"==", NormalizeDouble(1.34929 , 5))) Alert("AvsB Pass"); // It does pass using the AvsB routine!elseAlert("AvsB FAIL. ROUNDOFF BUG");
Ecco un'altra possibile routine che può confrontare, ma può anche normalizzare internamente sia A e/o B, e anche rilassare la differenza di confronto (di A-B o B-A) a un numero più grande basato su "cifre". Dubito che questa routine sia necessaria rispetto alla semplice "AvsB" di cui sopra, ma è offerta per il vostro uso come desiderato:
//+------------------------------------------------------------------+bool AvsB_nA_nB_digits(double A, string checkStr, double B, bool normalizeA, bool normalizeB, int digits)
{
//checkStr = StringTrimLeft(StringTrimRight(checkStr));
if (normalizeA) A = NormalizeDouble(A,MathMin(8,digits));
if (normalizeB) B = NormalizeDouble(B,MathMin(8,digits));
double diff;
switch(digits)
{
case0 : diff = 0.5; break; // Or 1.0 ??case1 : diff = 0.1; break;
case2 : diff = 0.01; break;
case3 : diff = 0.001; break;
case4 : diff = 0.0001; break;
case5 : diff = 0.00001; break;
case6 : diff = 0.000001; break;
case7 : diff = 0.0000001; break;
case8 : diff = 0.00000001; break;
case9 : diff = 0.000000001; break;
case10 : diff = 0.0000000001; break;
case11 : diff = 0.00000000001; break;
case12 : diff = 0.000000000001; break;
case13 : diff = 0.0000000000001; break;
case14 : diff = 0.00000000000001; break;
default : diff = 0.000000000000001; break; // 15 decimal places max (I think)
}
if (checkStr == ">" ){if (A - B > diff)return(true);elsereturn(false);}
elseif(checkStr == "<" ){if (B - A > diff)return(true);elsereturn(false);}
elseif(checkStr == ">="){if (A - B > -diff)return(true);elsereturn(false);}
elseif(checkStr == "<="){if (B - A > -diff)return(true);elsereturn(false);}
elseif(checkStr == "!="){if (MathAbs(A - B) > diff)return(true);elsereturn(false);}
elseif(checkStr == "=" || checkStr == "=="){if (MathAbs(A - B) < diff)return(true);elsereturn(false);}
else {Print("Sorry, bad usage: AvsB(A, checkStr, B). Wrong checkStr value: ",checkStr);}
return(false);
} // end of AvsB_nA_nB_digits//+------------------------------------------------------------------+
L'uso di "Point" o "Point/2.0" non è un valore di differenza molto buono, IMO. L'errore di arrotondamento introdotto da NormalizeDouble (che mi ha bruciato oggi), è certamente molto più piccolo di 8 cifre, più probabilmente 15 cifre.
Volete il valore più grande che non può essere considerato un errore di arrotondamento o, equivalentemente, il valore più piccolo che non può essere considerato un cambiamento di prezzo. Poiché i prezzi possono cambiare solo di un multiplo di punto, punto/2 è proprio questo.
Il valore doppio dal broker potrebbe essere ovunque da 1.23457500000000 a 1.23458499999999999 ed essere ancora considerato lo stesso prezzo 1.23458.
Se avessi usato questo, non avresti avuto il problema:
tonny: *Usa NormalizeDouble solo nei calcoli che coinvolgono un valore doppio, non ovunque ci sia un doppio.
O semplicemente non usate affatto NormalizeDouble(), la maggior parte delle volte quando viene usato non c'è assolutamente bisogno di usarlo. . . l'errore 4107 può essere affrontato usando NormalizeDouble(), ma ci sono altri modi. Qualsiasi prezzo che proviene da variabili predefinite o funzioni di serie temporali non avrà mai bisogno di essere normalizzato, e nemmeno il risultato di un intero moltiplicato per Point.
Se è per il confronto, allora si potrebbe facilmente creare la propria funzione:
È solo un pensiero.
Se è per il confronto, si potrebbe facilmente creare la propria funzione:
È solo un pensiero.
È un buon pensiero, grazie :-)
L'uso di "Point" o "Point/2.0" non è un valore di differenza molto buono, IMO. L'errore di arrotondamento introdotto da NormalizeDouble (che mi ha bruciato oggi), è certamente molto più piccolo di 8 cifre, più probabilmente 15 cifre.
Visti i suggerimenti precedenti, ho apportato alcune modifiche e messo insieme la seguente routine che sembra funzionare bene (anche usando il "diff" a 15 cifre decimali), anche se non è stata ancora testata rigorosamente:
Here is a check of the obvious:
Ecco un'altra possibile routine che può confrontare, ma può anche normalizzare internamente sia A e/o B, e anche rilassare la differenza di confronto (di A-B o B-A) a un numero più grande basato su "cifre". Dubito che questa routine sia necessaria rispetto alla semplice "AvsB" di cui sopra, ma è offerta per il vostro uso come desiderato:
L'uso di "Point" o "Point/2.0" non è un valore di differenza molto buono, IMO. L'errore di arrotondamento introdotto da NormalizeDouble (che mi ha bruciato oggi), è certamente molto più piccolo di 8 cifre, più probabilmente 15 cifre.
Volete il valore più grande che non può essere considerato un errore di arrotondamento o, equivalentemente, il valore più piccolo che non può essere considerato un cambiamento di prezzo. Poiché i prezzi possono cambiare solo di un multiplo di punto, punto/2 è proprio questo.
Il valore doppio dal broker potrebbe essere ovunque da 1.23457500000000 a 1.23458499999999999 ed essere ancora considerato lo stesso prezzo 1.23458.
Se avessi usato questo, non avresti avuto il problema:
if (a > b)if (a >= b)if (a != b)dovremmo evitare di usare normalisedouble?
o forse... ho pensato che possiamo usare lafunzione MathRound
ex . doppio x= (MathRound( 1.37883 * 100000)) / 100000 ;
così possiamo fare la funzione
*Usa NormalizeDouble solo nei calcoli che coinvolgono un valore doppio, non ovunque ci sia un doppio.
dovremmo evitare di usare normalisedouble?
o forse... ho pensato che possiamo usare la funzione MathRound
ex . doppio x= (MathRound( 1.37883 * 100000)) / 100000 ;
Si finisce ancora con un doppio e ancora la possibilità di prezzo != prezzo
Sono arrivato a questa soluzione che trasforma i doppi in ints allo scopo di confrontare i doppi . . .
in modo che . . .
non sarà mai vero.