Pregunta a los maestros del MQL4. De nuevo sobre la doble comparación. - página 8

 
SK. писал (а):
VBAG:
No esperaría eso de ti.

Me retracto.
Me alegro de haberme equivocado en mis dudas.
 

A SK.

Tú lo sabes mejor. No considero que MQL sea un lenguaje de programación. Es un DIALECTO.

Por cierto, estoy harto de dos cosas en él:

1) no hay enumeración de operaciones, es decir, corchetes

2) volver - estás muy cansado de los paréntesis.

En definitiva, bien hecho, chicos.

Kernighan y Ritchie: un aplauso para ellos.

 
VBAG писал (а):
Retiro lo dicho.
Me alegro de haberme equivocado en mis dudas.


No tuvimos ninguna discusión :)

Depfy:

No considero que MQL sea un lenguaje de programación. Es un DIALECTO.

Probablemente sea una cuestión de terminología. Yo, por ejemplo, encuentro en MQL todos los atributos de un lenguaje completo. En cualquier caso, es uno de los pocos lenguajes (notablemente, el mejor), que permiten a los comerciantes mecanizar y automatizar sus actividades. Creo que este lenguaje es bastante satisfactorio al menos en el sentido de que sus posibilidades superan muchas veces las necesidades de la mayoría de los algoritmos (en otras palabras - si hubiera suficientes ideas bien pensadas, y los medios para su aplicación ya están disponibles).
 
SK. писал (а):
...

Tal como está, el valor inicial de la variable 123.00000000000 puede resultar ser 122.999999999999 en el momento en que se utilice en los cálculos. Y esto a pesar de que desde que se descubrió la variable, su valor nunca ha cambiado, sino que sólo ha sido solicitada por el programa para participar en otros cálculos.


De hecho, es por esto que hubo todo este alboroto. Por eso hemos decidido utilizar NormalizeDouble() lo más cerca posible del cálculo real, preferiblemente justo en la condición de las sentencias if, for, while.

¿Está seguro de lo que dice? ¿Si puede especificar la fuente de sus conocimientos?

Entonces tengo esta pregunta para usted

1? si el problema es recordar o leer una variable, ¿cómo puede ayudar NormalizeDouble() si el valor de retorno también se recuerda o se lee con un error?
2? ¿Por qué el esquema NormalizeDouble(value, digits) !OC! NormalizeDouble(valor, dígitos), donde !OC! - operador de comparación, ¿no funciona siempre? incluso si se inserta directamente en el if?
3? ¿Sabes cómo funciona NormalizeDouble() (algoritmo de la función)?
4? he escrito mi opinión al respecto, ¿qué te parece?

gravedad001 escribió (a):

...
Ya te hablé de la normalización. Primero dime por qué necesitas aplicarlo y luego cómo y dónde.

Esa es la pregunta clave, ¿no? Yo también lo he pensado durante mucho tiempo: "si entras doble, recibes doble " ¿Qué podría cambiar?
No he encontrado la respuesta exacta. Pero me imagino que es así

doble a = 2.000000000000
doble b = 2.000000000001
doble c = 1,999999999999

Todas estas variables son diferentes y se almacenan en la memoria con precisión hasta el último dígito.
En este caso, nosotros mismos definimos los signos (dígitos). Todo lo que no está definido se llena de ceros.

Si hubiéramos definido el doble a = 2,0, y está almacenado en memoria como 2,0000001 o 1,9999999, está claro que NormalizeDouble() no ayudaría, ¡porque devolvería un valor inexacto!
Creo que ese error no se produce casi nunca al memorizar el valor de una variable. Además, no creo que el número 2,0 se almacene como 1,999999999999999 a propósito, ya que cada carácter (dígito o punto) se almacena con un bit específico en la cadena de bits. Por lo tanto, el número 2,0 se almacena con seguridad como 2,00000...00.

El otro caso es cuando no determinamos los signos nosotros mismos:

a = 4.0;
b = 2.0;
c = a / b // - la operación de "división" la realiza el procesador, o más bien el coprocesador, y rellena el premenente con caracteres (dígitos).

Después de la operación puede ser:
La más común:
с = 2.000...0
с= 1.99999999...
с= 2.00000001...

es decir, el resultado suele diferir del valor real en una pequeña cantidad.

Los errores grandes ocurren muy raramente:
с = 2.3

Aquí hay dos explicaciones:
1) parte de la cadena de bits se vio afectada en la memoria al llamar a o b, es decir, las variables a y b se modificaron.
2) se ha producido un error durante la operación de "división".

Creo que la 2) es la más frecuente. Por qué no lo sé. Creo que tiene que ver con el hecho de que el coprocesador está pensado para ser altamente optimizado en detrimento de la inutilidad.

Al comparar una variable con el número 2.000...00, la igualdad obviamente fallará. No todos los bits serán iguales.

Ahora, NormalizeDouble() está aquí para ayudar.
NormalizeDouble() "arreglará" este pequeño error.
Como el error suele ser muy pequeño, el redondeo con una precisión pequeña siempre dará el resultado correcto.

Míralo de esta manera:
Redondea el número a = 2,111...11 al segundo dígito.
NormalizeDouble() escribirá 2,11 en una nueva variable y rellenará los bits restantes con ceros, ¡no con unos!
Creo que se verá así:

double MyNormalizeDouble(double value, int digits)
{
     int factor = MathRound( MathPow(10, digits) ); // factor - это множитель,
                                                       с помощью которого мы из VALUE сделаем целое число
     double result = MathRound(factor * value) / factor;
     return(result);
}
Aquí, he intentado explicar lo mejor posible por qué se necesita NormalizeDouble().

Hasta hace poco estaba completamente satisfecho con esta explicación, pero recientemente me he convencido de que este esquema no siempre funciona

¡NormalizarDoble(a, 2) ! NormalizeDouble(b, 2) donde !OC! - es un operador de comparación.
Aunque, según tengo entendido, ¡siempre debe funcionar!
Por lo tanto, ¡estaré encantado de recibir cualquier crítica razonada y comprensible!
 
gravity001:
SK. escribió (a):
...

Tal como está, el valor inicial de la variable 123.00000000000 puede resultar ser 122.999999999999 en el momento en que se utilice en los cálculos. Y esto a pesar de que desde que se descubrió la variable, su valor nunca ha cambiado, sino que sólo ha sido solicitada por el programa para participar en otros cálculos.

De hecho, es por esto que hubo todo este alboroto. Por eso tuve que usar NormalizeDouble() lo más cerca posible del cálculo real, preferiblemente directamente en la condición de las sentencias if, for, while.

¿Está seguro de lo que dice? ¿Podría indicar la fuente de sus conocimientos?
Estoy seguro. La fuente de sus conocimientos es su propia experiencia en la programación de MQL4 y las consultas de los desarrolladores.
1? Si el problema está en recordar o leer una variable, ¿cómo puede ayudar NormalizeDouble(), si el valor de retorno también se recuerda o se lee con un error?
NormalizeDouble() debe aplicarse inmediatamente antes de la operación de comparación. El resultado de la operación de comparación es un valor de tipo booleano, que nunca se "corrompe".
¡2? ¿Por qué el esquema NormalizeDouble(value, digits) ! NormalizeDouble(value, digits) , donde !OC! es el operador de comparación, no siempre funciona? incluso si lo insertas directamente en if?
No lo he dicho. Así es exactamente como funciona y eso es lo que debes hacer.
3? ¿Sabes cómo funciona NormalizeDouble() (algoritmo de la función)?
No, no lo sé. Por favor, remítalo a los desarrolladores.
4? He escrito mi opinión sobre este tema, ¿qué te parece?
Su opinión es interesante, pero esta cuestión está resuelta desde hace tiempo. Es mejor utilizar las recomendaciones de los desarrolladores y no reinventar la rueda.
 
SK. писал (а):
gravedad001:

2. ¿Por qué el esquema NormalizeDouble(value, digits) !OC! NormalizeDouble(value, digits) , donde !OC! es un operador de comparación, no siempre funciona, incluso si lo insertas directamente en if?
No lo he dicho. Así es exactamente como funciona y así es como debes hacerlo.

Aquí hay más opiniones sobre este tema

'De nuevo sobre la comparación de dos dobles', ¡1 página desde el primer puesto!

Entero 24.12.2006 15:23

Desgraciadamente, la construcción NormalizeDouble(x-y,Digits) no es idéntica a la construcción NormalizeDouble(x,Digits) - NormalizeDouble(y,Digits)

Renat 24.12.2006 16:15

Y no debería ser idéntico. La primera es correcta.

Creo que la construcción es
if (NormalizeDouble(x,Digits) - NormalizeDouble(y,Digits) != 0)
y la construcción
if (NormalizeDouble(x,Digits) != NormalizeDouble(y,Digits))
son idénticos.

¿Qué te parece?
 
gravity001:

Renat 24.12.2006 16:15

Y no debe ser idéntico. La primera es correcta.

Creo que la construcción
if(NormalizeDouble(x,Digits) - NormalizeDouble(y,Digits) != 0)
y la construcción
if (NormalizeDouble(x,Digits) != NormalizeDouble(y,Digits))
son idénticos.

¿Qué te parece?


¿Y la opinión de Renat no es interesante? ¿No le interesa la opinión del director general de la empresa que desarrolla la MT?

¿O es usted como la anciana del cuento de Pushkin? ¡Sólo quiero-quiero-quiero! Recuerda cómo termina el cuento. "El pez no dijo nada. Movió la cola y se alejó nadando hacia el mar azul. Esperó mucho tiempo junto al mar para obtener una respuesta. No esperó, se volvió hacia la anciana..."

 
SK. писал (а):
La primera es la gravedad001:


Renat 24.12.2006 16:15

Y no debe ser idéntico. La primera es correcta.

Creo que la construcción
if(NormalizeDouble(x,Digits) - NormalizeDouble(y,Digits) != 0)
y la construcción
if (NormalizeDouble(x,Digits) != NormalizeDouble(y,Digits))
son idénticos.

¿Qué te parece?



¿Y la opinión de Renat no es interesante? ¿No le interesa la opinión del director general de la empresa que desarrolla la MT?


¿O es usted como la anciana del cuento de Pushkin? ¡Sólo quiero-quiero-quiero! Recuerda cómo termina el cuento. "El pez no dijo nada. Movió la cola y se alejó nadando hacia el mar azul. Esperó junto al mar durante mucho tiempo para obtener una respuesta. No esperó, se volvió hacia la anciana..."



Bueno, Renat dijo que la primera forma es correcta y la segunda es incorrecta, y tú dijiste que la segunda forma es correcta, ¿verdad?

2? ¿Por qué el esquema NormalizeDouble(value, digits) !OC! NormalizeDouble(value, digits) , donde !OC! es un operador de comparación, no siempre funciona, incluso si lo insertas directamente en if?
No lo he dicho. Así es exactamente como funciona, y así es como debe hacerse.
 

Lo he dicho en el sentido de una comparación más o menos:

if (NormalizeDouble(x,Digits) > NormalizeDouble(y,Digits))

lo que significa que las construcciones del tipo no siempre funcionan:

double a = NormalizeDouble(x,Digits);
double b = NormalizeDouble(y,Digits);
 
if (a > b)
  {
  ...
  }

Es decir, NormalizeDouble() debe insertarse justo en la cabecera del operador, lo más cerca posible de donde se calcula la operación de comparación.

En cuanto a la opinión de los desarrolladores, no pretendo discutirla.

Y entonces... ese hilo trataba de una construcción totalmente diferente:

 
SK. писал (а):

Lo he dicho dando a entender una comparación más o menos importante:

if (NormalizeDouble(x,Digits) > NormalizeDouble(y,Digits))
No he comprobado ni más ni menos, pero sí la igualdad.
Tuve errores de comparación cuando utilicé esta construcción:

if (NormalizeDouble(x, digits) == NormalizeDouble(y, digits))
{
    ...
}
¿Por qué, no lo sabes?
Razón de la queja: