Errores, fallos, preguntas - página 711

 
sergeev:
Utiliza las clases.

Sí, así es. No me había dado cuenta. Ni siquiera lo recuerdo, se ha sugerido antes.

Así es como resultó:

struct Buff { double b[]; };
//---
Buff lbuff[];
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
   int i=2,j=1000;
//---
   ArrayResize(lbuff,i);
   ArrayResize(lbuff[0].b,j);
   ArrayResize(lbuff[1].b,j);
  }
Rosh:
Mira la sección de operaciones de sobrecarga por ejemplo para la clase CMatrix, tal vez esto te convenga.
Gracias, lo estudiaré.
 
Rosh:

El hecho es que un número real se almacena en la memoria con no más de 17 dígitos significativos.

Pruebe este ejemplo para sentir la diferencia:

Se corregirá la descripción en la ayuda.

Sí, Renat ya ha explicado más arriba que Print() emitedatos de tipo doble con una precisión de 4, no de 16 dígitos decimales después del punto. Ese era todo el punto de fricción desde el punto de vista del usuario.

 
Yedelkin:

Sí, Renat ya ha explicado más arriba que Print() emitedatos de tipo doble a 4, no a 16 dígitos decimales después del punto. Ese era el problema desde el punto de vista del usuario.

No, Print() imprime en formato %.16G, lo que significa que intentará imprimir un número con un punto y 16 dígitos significativos. En este caso, el número almacenado es 199,999999999997, que tiene 17 dígitos significativos (3 dígitos antes del punto decimal + 14 después del punto decimal). Cuando intento imprimir 16 dígitos, comienza el redondeo, el 7 se redondea a 10, se pasa a un dígito más alto, y el 9 está ahí. Comienza el principio del dominó, el número impreso se redondea a 200.

Prueba con un ejemplo:

void OnStart()
  {
   double a,b;

   a=7.0/200.0;
   b=7.0/a;
   Print("Print(b)=",b);
   Print("Print(DoubleToString(b,16))=",DoubleToString(b,16));
   double epsilon=MathPow(10,-13);
   Print("-------- После вычитания ",epsilon,"---------");
   b=b-epsilon;
   Print("Print(b)=",b);
   Print("Print(DoubleToString(b,16))=",DoubleToString(b,16));

   
  }

Mira PrintFormat().

 
Rosh:

No, Print() sale en formato %.16G, lo que significa que intentará sacar un número con un punto y 16 dígitos significativos. En este caso, el número almacenado es 199,99999999999997, que tiene 17 dígitos significativos (3 dígitos antes del punto decimal + 14 después del punto decimal). Cuando intento imprimir 16 dígitos, comienza el redondeo, el 7 se redondea a 10, se pasa al siguiente dígito más alto, y el 9 está ahí. Comienza el principio del dominó, el número impreso se redondea a 200.

Echa un vistazo a PrintFormat().

Ahora entiendo por qué nos centramos en el número de cifras significativas que se almacenan.

...Pero si un número real se almacena con no más de 17 cifras significativas (en nuestro caso es 199,999999999997), ¿de dónde salen las cifras significativas?

MP 0 victorg2 (EURUSD,M1) 11:04:42 Print(DoubleToString(b,16))=199.9999999999999716

? (He contado 19 altas)
 

"En condiciones de combate, el número de pi puede llegar a ser de cuatro".

DoubleToString funciona de forma ligeramente diferente al formato en la impresora (que se deja a la CRT)

DoubleToString convierte las partes enteras y fraccionarias en cadenas por separado y con un algoritmo ligeramente más rápido que el del formato estándar.

Документация по MQL5: Основы языка / Типы данных / Вещественные типы (double, float)
Документация по MQL5: Основы языка / Типы данных / Вещественные типы (double, float)
  • www.mql5.com
Основы языка / Типы данных / Вещественные типы (double, float) - Документация по MQL5
 
stringo:

En DoubleToString las partes enteras y fraccionarias se convierten en cadenas por separado y mediante un algoritmo ligeramente más rápido que el del formato estándar.

Pero luego resulta que en la memoria se almacenan algo más de 17 dígitos significativos. Si no, ¿de dónde saldrían las partes enteras y fraccionarias para las conversiones a cadenas? Es decir, independientemente de si es Print() o DoubleToString(), obtienen sus datos de algún sitio (si hablamos específicamente de almacenar "en memoria con no más de 17 dígitos significativos").

...Quizás, claro, me he quedado con la frase "almacenar en la memoria", y no lo entiendo bien debido a mi ignorancia de la naturaleza del almacenamiento de los números reales.

 
Yedelkin:

Pero luego resulta que hay algo más de 17 dígitos significativos almacenados en la memoria . Si no, ¿de dónde salen las partes enteras y fraccionarias para las conversiones a cadenas? Es decir, ya sea Print() o DoubleToString(), obtienen sus datos de alguna parte (si hablamos específicamente de almacenar "en memoria con no más de 17 dígitos significativos").

...Puede que, claro, me haya enganchado a la frase "almacenar en la memoria", y no lo entienda del todo bien debido a mi ignorancia de la naturaleza del almacenamiento de los números reales.

A veces se pueden almacenar hasta 20 dígitos significativos, pero no está garantizado. Y, en general, cuanto mayor es el número en la parte entera, menos preciso es en la parte fraccionaria.

¿Por qué necesitas 16 decimales? ¿Interés académico?

Документация по MQL5: Основы языка / Типы данных / Вещественные типы (double, float)
Документация по MQL5: Основы языка / Типы данных / Вещественные типы (double, float)
  • www.mql5.com
Основы языка / Типы данных / Вещественные типы (double, float) - Документация по MQL5
 
stringo:

A veces se almacenan hasta 20 dígitos significativos, pero no está garantizado. Y, en general, cuanto mayor es el número en la parte entera, menos preciso es en la parte fraccionaria.

¿Por qué necesitas 16 decimales? ¿Interés académico?

:) Para no jugar al teléfono estropeado, veamos la historia de fondo.

Aquí victorg hizo una pregunta sobre el trabajo de la función Print() y los valores que produce.

Aquí le mostré la razón.

Ya que no quería molestarse con los problemas de la función Print(),

Me atreví a señalar que la descripción de la función Print()dice que "los datos del tipo double se imprimen con una precisión de 16 dígitos decimales después del punto".En realidadresultó que la función Print() imprime datos algo redondos con un ejemplo concreto adjunto.

Entonces se produjo una acalorada discusión, al final nadie pudo refutar mi ejemplo, y Renat esbozó la primera versión y dijo que el libro de referencia sería corregido.

Unos días más tarde, Roche presentó una segunda versión, en la que se mencionaba el número 17.

Al unirse a la discusión, sugirió una tercera versión, a saber "En DoubleToString las partes enteras y fraccionarias se convierten por separado en cadenas y mediante un algoritmo ligeramente más rápido que el del formateo estándar" Es decir, ya resultó ser una cuestión de velocidad del algoritmo.

Entonces llamé su atención sobre el hecho de que, en general, era del tamaño del número almacenado de la segunda versión de Roche.

estrangulamiento:

¿Por qué necesitas 16 decimales? ¿Interés académico?

Ahora puedes responder a esas preguntas. He dado un ejemplo en el que la función Print() produce datos redondeados. No he preguntado por las razones de ese comportamiento. Mi ejemplo no fue refutado, sino que simplemente se me aconsejó que utilizara una función diferente y comenzó a explicar las razones. Y entre esas explicaciones aparecía la mención de 16 (17) decimales. Como no todo me quedaba claro en esas explicaciones, hice preguntas "sobre la marcha". - Así que ni siquiera se trataba de un interés académico por mi parte, sino simplemente de un deseo de comprender lo que la idea intentaba transmitirme.

 
Yedelkin:

. . . Así que ni siquiera se trata de un interés académico por mi parte, sino simplemente de un deseo de entender el mensaje que intentaba transmitir.

No podría estar más de acuerdo. El interés académico no tiene nada que ver.

Lea"número real" en la documentación. Norma IEEE 754, hay 15 dígitos significativos en la tabla para eldoble . Teniendo en cuenta esto, hay cuatro opciones - 15, 16, 17 dígitos significativos y la opción cuando la parte entera y la parte fraccionaria se almacenan por separado. ¡Pero no funciona así! ¿Qué tiene que ver el interés académico? Se trata más bien de lógica formal elemental, que, por cierto, es la base de este lenguaje de programación.

Me parece que el programador debe escribir programas, no investigar el compilador.

PS

Me gustaría aprovechar esta oportunidad para aclarar:

Si aumento el tamaño de un array dinámico mediante la función ArrayResize(), ¿está garantizado que los datos colocados previamente en él se conservarán? Tal vez este punto debería mencionarse explícitamente en la documentación (en la descripción de la función ArrayResize()).Si alguien lo sabe, por favor, aconséjelo.

 
victorg:

Si aumento el tamaño de un array dinámico con ArrayResize(), ¿está garantizado que los datos colocados previamente en él se conservarán? Tal vez este punto debería mencionarse explícitamente en la documentación (en la descripción de la función ArrayResize()).Si alguien lo sabe, por favor, aconséjelo.

Lo serán cuando se aumente el tamaño, de lo contrario no tiene sentido dicha función.