Erros, bugs, perguntas - página 711

 
sergeev:
Utilizar as aulas.

Sim, é verdade. Não me tinha apercebido. Nem sequer me lembro, já foi sugerido antes.

Foi assim que se revelou:

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:
Veja a secção de operações de sobrecarga, por exemplo para a classe CMatrix, talvez isto lhe sirva.
Obrigado, irei estudá-lo.
 
Rosh:

O facto é que um número real é armazenado na memória com não mais do que 17 dígitos significativos.

Experimente este exemplo para sentir a diferença:

Vamos corrigir a descrição na ajuda.

Sim, Renat já explicou acima que a impressão() produzdados de tipo duplo com precisão de 4 e não 16 dígitos decimais após o ponto. Esse foi o ponto de fricção do ponto de vista do utilizador.

 
Yedelkin:

Sim, Renat já explicou acima que Print() produzdados de tipo duplo a 4, não a 16 dígitos decimais após o ponto. Esse era o problema do ponto de vista do utilizador.

Não, Print() imprime em formato %.16G, o que significa que tentará imprimir um número com um ponto e 16 dígitos significativos. Neste caso, o número armazenado é 199,999999999999999997, que tem 17 dígitos significativos (3 dígitos antes do ponto decimal + 14 após o ponto decimal). Quando tento imprimir 16 dígitos, o arredondamento começa, 7 é arredondado para 10, um vai para dígito superior, e 9 está lá. O princípio do dominó começa, o número impresso é arredondado para 200.

Experimente um exemplo:

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

   
  }

Veja-se PrintFormat().

 
Rosh:

Não, Print() produz em formato %.16G, o que significa que tentará produzir um número com uma paragem completa e 16 dígitos significativos. Neste caso, o número armazenado é 199,99999999999999999997, que tem 17 dígitos significativos (3 dígitos antes do ponto decimal + 14 após o ponto decimal). Quando tento imprimir 16 dígitos, o arredondamento começa, 7 é arredondado para 10, um vai para o dígito superior seguinte, e 9 está lá. O princípio do dominó começa, o número impresso é arredondado para 200.

Dê uma vista de olhos em PrintFormat().

Agora compreendo porque nos concentramos no número de números significativos que estão a ser armazenados.

...Mas se um número real é armazenado com não mais de 17 dígitos significativos (no nosso caso é 199,9999999999999997), de onde vêm os dígitos significativos?

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

? (contei 19 descargas)
 

"Em condições de combate, o número de pi pode chegar a quatro".

DoubleToString funciona de forma ligeiramente diferente da formatação na impressora (que é deixada ao CRT)

DoubleToString converte partes inteiras e fracionárias em cordas separadamente e com um algoritmo ligeiramente mais rápido do que a formatação padrão.

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

Em DoubleToString, o inteiro e as partes fracionárias são convertidos em cordas separadamente e por um algoritmo ligeiramente mais rápido do que a formatação padrão.

Mas depois verifica-se que um pouco mais de 17 dígitos significativos são guardados na memória . Caso contrário, de onde viriam o inteiro e as partes fracionárias para conversões em cordas? Isto é, independentemente de ser Print() ou DoubleToString(), eles obtêm os seus dados de algum lugar (se estivermos a falar especificamente de armazenar "em memória com não mais de 17 dígitos significativos").

...Talvez, claro, tenha sido apanhado pela frase "armazenar em memória", e não percebo bem devido à minha ignorância sobre a natureza de armazenar números reais.

 
Yedelkin:

Mas depois verifica-se que existem pouco mais de 17 dígitos significativos armazenados na memória . Caso contrário, de onde vêm o inteiro e as partes fracionárias para conversões em cordas? Isto é, se imprimir() ou DoubleToString(), eles obtêm os seus dados de algum lugar (se estivermos a falar especificamente de armazenar "em memória com não mais de 17 dígitos significativos").

...Talvez, claro, tenha ficado viciado na frase "armazenar em memória", e não percebo bem devido à minha ignorância da natureza de armazenar números reais.

Por vezes são armazenados até 20 dígitos significativos, mas não garantidos. E, em geral, quanto maior for o número na parte inteira, menos precisa é na parte fracionária.

Porque é que precisa de 16 casas decimais? Interesse académico?

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

Por vezes são armazenados até 20 dígitos significativos, mas não é garantido. E, em geral, quanto maior for o número na parte inteira, menos precisa é na parte fracionária.

Porque é que precisa de 16 casas decimais? Interesse académico?

:) A fim de não jogar ao telefone estragado, vejamos o fundo da história.

Aqui o victorg fez uma pergunta sobre o trabalho da função Print() e os valores que produz.

Aqui mostrei-lhe a razão.

Uma vez que não se queria preocupar com problemas da função de impressão(),

Tive a coragem de salientar que a descrição da função Print()diz que "os dados do tipo duplo são impressos com uma precisão de 16 dígitos decimais após o ponto. Na realidade,verificou-se que a função Print() imprime dados algo arredondados com um exemplo concreto anexado.

Seguiu-se então uma discussão acesa, no final ninguém conseguiu refutar o meu exemplo, e Renat delineou a primeira versão e disse que o livro de referência seria corrigido.

Alguns dias mais tarde, Roche fez uma segunda versão, onde o número 17 foi mencionado.

Tendo participado na discussão, sugeriu uma terceira versão, a saber"No DoubleToString, o inteiro e as partes fracionárias são convertidos separadamente em cordas e por um algoritmo ligeiramente mais rápido do que a formatação padrão", isto é, já se revelou ser uma questão de velocidade do algoritmo.

Depois chamei a vossa atenção para o facto de que, em geral, era aproximadamente do tamanho do número armazenado da segunda versão da Roche.

stringo:

Porque é que precisa de 16 casas decimais? Interesse académico?

Agora pode responder a essas perguntas. Dei um exemplo em que a função Print() produz dados arredondados. Não perguntei sobre as razões de tal comportamento. O meu exemplo não foi desmentido, mas fui apenas aconselhado a usar uma função diferente e comecei a explicar as razões. E entre estas explicações apareceu uma menção de 16 (17) casas decimais. Uma vez que nem tudo era claro para mim nessas explicações, fiz perguntas "à medida que ia avançando". - Portanto, nem sequer foi um interesse académico da minha parte, mas apenas um desejo de compreender o que a ideia me estava a tentar transmitir.

 
Yedelkin:

. . . Portanto, não é sequer um interesse académico da minha parte, mas apenas um desejo de compreender que mensagem eu estava a tentar transmitir.

Não podia estar mais de acordo. O interesse académico não tem nada a ver com isso.

Ler"número real" na documentação. Norma IEEE 754, a tabela para o dobro tem 15 dígitos significativos. Tendo isto em conta, já existem quatro opções - 15, 16, 17 dígitos significativos e opção quando a parte inteira e a parte fracionada são armazenadas separadamente. Mas não funciona assim! O que é que o interesse académico tem a ver com isto? Trata-se mais de lógica formal elementar, que, a propósito, é a base desta linguagem de programação.

Parece-me que o programador deve escrever programas, e não investigar o compilador.

PS

Gostaria de aproveitar esta oportunidade para esclarecer:

Se eu aumentar o tamanho de uma matriz dinâmica usando a função ArrayResize(), é garantido que os dados previamente colocados na mesma serão preservados? Talvez este ponto deva ser explicitamente mencionado na documentação (na descrição da função ArrayResize()).Se alguém souber, por favor aconselhe.

 
victorg:

Se eu aumentar o tamanho de um array dinâmico com o ArrayResize(), é garantido que os dados previamente colocados no mesmo serão preservados? Talvez este ponto devesse ser explicitamente mencionado na documentação (na descrição da função ArrayResize()).Se alguém souber, por favor aconselhe.

Estarão quando o tamanho for aumentado, caso contrário não faz sentido uma tal função.