Errori, bug, domande - pagina 711

 
sergeev:
Utilizzare le classi.

Sì, proprio così. Non me ne ero reso conto. Non me lo ricordo nemmeno, è stato suggerito prima.

Ecco come è andata a finire:

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:
Date un'occhiata alla sezione delle operazioni di sovraccarico per esempio per la classe CMatrix, forse questo farà al caso vostro.
Grazie, lo studierò.
 
Rosh:

Il fatto è che un numero reale è memorizzato con non più di 17 cifre significative.

Provate questo esempio per sentire la differenza:

La descrizione nella guida sarà corretta.

Sì, Renat ha già spiegato sopra che Print() emettedati di tipo doppio precisi a 4, non 16 cifre decimali dopo il punto. Questo era il punto critico dal punto di vista dell'utente.

 
Yedelkin:

Sì, Renat ha già spiegato sopra che Print() emettedati di tipo doppio a 4, non a 16 cifre decimali dopo il punto. Questo era il problema dal punto di vista dell'utente.

No, Print() stampa nel formato %.16G, il che significa che cercherà di stampare un numero con un punto e 16 cifre significative. In questo caso, il numero memorizzato è 199,9999999999999997, che ha 17 cifre significative (3 cifre prima del punto decimale + 14 dopo il punto decimale). Quando provo a stampare 16 cifre, inizia l'arrotondamento, 7 viene arrotondato a 10, uno va alla cifra più alta, e 9 è lì. Inizia il principio del domino, il numero stampato viene arrotondato a 200.

Provate un esempio:

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));

   
  }

Guardate PrintFormat().

 
Rosh:

No, Print() emette in formato %.16G, il che significa che tenterà di emettere un numero con un punto e 16 cifre significative. In questo caso, il numero memorizzato è 199.999999999999999997, che ha 17 cifre significative (3 cifre prima del punto decimale + 14 dopo il punto decimale). Quando provo a stampare 16 cifre, inizia l'arrotondamento, 7 viene arrotondato a 10, si passa alla cifra successiva più alta, e 9 è lì. Inizia il principio del domino, il numero stampato viene arrotondato a 200.

Date un'occhiata a PrintFormat().

Ora capisco perché ci concentriamo sul numero di numeri significativi memorizzati.

...Ma se un numero reale è memorizzato con non più di 17 cifre significative (nel nostro caso è 199,999999999999999997), da dove vengono le cifre significative?

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

? (Ho contato 19 scarichi)
 

"In condizioni di combattimento, il numero di pi può arrivare a quattro".

DoubleToString funziona in modo leggermente diverso dalla formattazione nella stampante (che è lasciata al CRT)

DoubleToString converte le parti intere e frazionarie in stringhe separatamente e con un algoritmo leggermente più veloce della formattazione standard.

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

In DoubleToString le parti intere e frazionarie sono convertite in stringhe separatamente e con un algoritmo leggermente più veloce della formattazione standard.

Ma poi si scopre che un po' più di 17 cifre significative sono memorizzate . Altrimenti da dove verrebbero le parti intere e frazionarie per le conversioni in stringhe? Cioè, indipendentemente dal fatto che sia Print() o DoubleToString(), prendono i loro dati da qualche parte (se stiamo parlando specificamente di memorizzare "in memoria con non più di 17 cifre significative").

...Forse, naturalmente, mi sono fatto prendere dalla frase "memorizzare in memoria", e non ho capito bene a causa della mia ignoranza sulla natura della memorizzazione dei numeri reali.

 
Yedelkin:

Ma poi si scopre che ci sono poco più di 17 cifre significative memorizzate . Altrimenti, da dove vengono le parti intere e frazionarie per le conversioni in stringhe? Cioè, che sia Print() o DoubleToString(), prendono i loro dati da qualche parte (se stiamo parlando specificamente di memorizzare "in memoria con non più di 17 cifre significative").

...Forse, naturalmente, mi sono fissato con la frase "memorizzare in memoria", e non ho capito bene a causa della mia ignoranza sulla natura della memorizzazione dei numeri reali.

A volte vengono memorizzate fino a 20 cifre significative, ma non è garantito. E in generale, più grande è il numero nella parte intera, meno preciso è nella parte frazionaria.

Perché avete bisogno di 16 cifre decimali? Interesse accademico?

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

A volte vengono memorizzate fino a 20 cifre significative, ma non è garantito. E in generale, più grande è il numero nella parte intera, meno preciso è nella parte frazionaria.

Perché avete bisogno di 16 cifre decimali? Interesse accademico?

:) Per non giocare al telefono viziato, diamo un'occhiata ai retroscena.

Qui victorg ha fatto una domanda sul lavoro della funzione Print() e sui valori che produce.

Qui gli ho mostrato la ragione.

Poiché non voleva preoccuparsi dei problemi della funzione Print(),

Ho avuto il coraggio di far notare che la descrizione della funzione Print()dice che "i dati di tipo doppio sono stampati con una precisione di 16 cifre decimali dopo il punto".In realtà si èscoperto che la funzione Print() stampa dati un po' arrotondati con un esempio concreto allegato.

Poi seguì un'accesa discussione, alla fine nessuno fu in grado di confutare il mio esempio, e Renat delineò la prima versione e disse che il libro di riferimento sarebbe stato corretto.

Qualche giorno dopo, Roche ha presentato una seconda versione, in cui il numero 17 era menzionato.

Essendo entrato nella discussione, hai suggerito una terza versione, cioè"In DoubleToString le parti intere e frazionarie sono convertite separatamente in stringhe e con un algoritmo leggermente più veloce della formattazione standard" cioè si è già rivelato essere una questione di velocità dell'algoritmo.

Poi ho richiamato l'attenzione sul fatto che, in generale, era circa la dimensione del numero memorizzato dalla seconda versione di Roche.

stringo:

Perché avete bisogno di 16 cifre decimali? Interesse accademico?

Ora puoi rispondere a queste domande. Ho dato un esempio in cui la funzione Print() emette dati arrotondati. Non ho chiesto le ragioni di tale comportamento. Il mio esempio non è stato confutato, ma mi è stato solo consigliato di usare una funzione diversa e ho iniziato a spiegare le ragioni. E tra queste spiegazioni appariva una menzione di 16 (17) cifre decimali. Poiché non tutto mi era chiaro in quelle spiegazioni, ho fatto domande "man mano". - Quindi non era nemmeno un interesse accademico da parte mia, ma semplicemente il desiderio di capire cosa l'idea stava cercando di trasmettermi.

 
Yedelkin:

. . . Quindi non si tratta nemmeno di un interesse accademico da parte mia, ma solo di un desiderio di capire quale messaggio stavo cercando di trasmettere.

Non potrei essere più d'accordo. L'interesse accademico non c'entra niente.

Leggete"numero reale" nella documentazione. Lo standard IEEE 754, la tabella per il doppio ha 15 cifre significative. Tenendo conto di questo, ci sono quattro opzioni - 15, 16, 17 cifre significative e l'opzione quando la parte intera e la parte frazionaria sono memorizzate separatamente. Ma non funziona così! Cosa c'entra l'interesse accademico? Si tratta piuttosto di logica formale elementare, che, tra l'altro, è la base di questo linguaggio di programmazione.

Mi sembra che il programmatore dovrebbe scrivere programmi, non indagare sul compilatore.

PS

Vorrei cogliere l'occasione per chiarire:

Se aumento le dimensioni di un array dinamico usando la funzione ArrayResize(), è garantito che i dati precedentemente inseriti in esso saranno conservati? Forse questo punto dovrebbe essere menzionato esplicitamente nella documentazione (nella descrizione della funzione ArrayResize()).Se qualcuno lo sa, per favore consigliatelo.

 
victorg:

Se aumento le dimensioni di un array dinamico con ArrayResize(), è garantito che i dati precedentemente inseriti siano conservati? Forse questo punto dovrebbe essere menzionato esplicitamente nella documentazione (nella descrizione della funzione ArrayResize()).Se qualcuno lo sa, per favore consigliatelo.

Lo saranno quando le dimensioni saranno aumentate, altrimenti non ha senso una funzione del genere.