Características da linguagem mql5, subtilezas e técnicas - página 144

 
Igor Makanu:

No NaN é necessário verificar adicionalmente

Há aí um número normal. A verificação é simples - dividir por aquilo por que se divide, depois verificar se é zero.

 
fxsaber:

Há aí um número normal. A verificação é simples - aquilo por que se divide, verifica-se se é zero.

mas não se verifica zero neste código:

// Неправильно написанная функция.
double WrongFunc( const double Num )
{
  return(Num ? 1 / (0.1 * Num) : 0);
}

a expressãoNum ? em MQL será verdadeira se não houver valor 0x0000000000000000 em 8 bytes de duplo

em qualquer outro caso, esta expressão(Num ?) será verdadeira


no início deste mês falei em não verificar o bool no MQL - a resposta é sem perda de dados, por isso não há necessidade - é o mesmo problema, poderia tentar dividir a expressão em NaN - os bytes duplos não estarão vazios?


Não o posso verificar agora, mas é provavelmente a forma de o fazer:

// Неправильно написанная функция.
double WrongFunc( const double Num )
{
  return(Num && !(Num!=Num) ? 1 / (0.1 * Num) : 0);
}
 
Igor Makanu:

Mas não se verifica zero neste código:

Não o posso verificar agora, mas provavelmente tem de ser assim:

Não vai funcionar. O número é um número normal no exemplo do acidente. O bool não tem nada a ver com isto.

 
fxsaber:

Não vai funcionar. No exemplo do acidente, o Num é um número normal. O bool não tem nada a ver com isto.

Pesquisa de NaN verificada

//+------------------------------------------------------------------+
void OnStart()
{
   union ULongTODouble {
      ulong ul;
      double d;
   } ULongDouble;

   ulong i = 0xFFFFFFFFFFFFFFFF;
   while(i > 0 && !IsStopped()) {
      ULongDouble.ul = i;
      if(ULongDouble.d != ULongDouble.d) Print("NaN, i = ", i);
      i--;
   }

}
//_______________________________________________________________________

funciona realmente em MQL5, pode começar o loop a partir do zero, mas terá de esperar mais tempo.

é uma questão de dupla precisão - está ligada a um tipo de processador específico, por isso fiz os comentários acima de que o erro não é reproduzido


UPD:

é melhor concluir dessa forma:

if(ULongDouble.d != ULongDouble.d) Print("NaN, d = ", ULongDouble.d); // tst1 (EURUSD,H1)	NaN, d = -nan
 
Hmmm, por que razão seria expulsa uma excepção quando a divisão por zero duplas? Bem, haveria inf, há algumas tretas.
 
Igor Makanu:

A sua pergunta é geralmente uma questão de precisão do duplo - está geralmente ligada a um tipo específico de processador, razão pela qual os comentários acima sobre o erro não são reproduzíveis

É reprodutível em qualquer tipo. Para ser honesto, não compreendo porque há tantas conversas sobre este tema. Bem, eles multiplicaram dois números não zero e obtiveram zero. Sem magia.


Todos compreendem este código, não é verdade?

void OnStart()
{
  double d = 0.5;  
  int Count = 1;
  
  while (d *= d)
    Count <<= 1;
    
  Print(Count);
}


Há aqui uma situação absolutamente semelhante, quando d se transforma em zero.

 
fxsaber:

Sem magia.

que é a magia, não impressa desta forma:

void OnStart()
{
   union ULongTODouble {
      ulong ul;
      double d;
   } ULongDouble;

   ulong nan = 18446744073708624091;
   ULongDouble.ul = nan;
   
   Print("ULongDouble.d != ULongDouble.d ", ULongDouble.d != ULongDouble.d);
   double d_value = 0.1 * ULongDouble.d;
   bool b_value = d_value;
   Print("b_value =  ", b_value);
   Print("d_value =  ", d_value);
   Print("1 / d_value =  ", 1 / d_value);

}
//_______________________________________________________________________

2019.10.28 16:25:28.643 tst1 (EURUSD,H4) ULongDouble.d != ULongDouble.d verdadeiro

2019.10.28 16:25:28.643 tst1 (EURUSD,H4) b_value = verdadeiro

2019.10.28 16:25:28.643 tst1 (EURUSD,H4) d_value = nan

2019.10.28 16:25:28.667 tst1 (EURUSD,H4) divisão zero em 'tst1.mq5' (28,31)



fxsaber:

A situação é absolutamente a mesma aqui, quando d se torna zero.

No seu exemplo, quando 0,1 * Num ? é um bool - é uma simples presença de um bit em 8 bytes de duplo

e quando 0,1 * Num é um duplo, então se perder a precisão, pode ir para Nan e obter uma divisão zero

 
Não consegui essa.
#include <TypeToBytes.mqh> // https://www.mql5.com/ru/code/16280

void OnStart()
{
  double Num = 0;
  
  _W(Num) = (uchar)1;
  
  Print(Num < DBL_MIN); // true
  Print(DBL_MIN);       // 2.225073858507201e-308
  Print(Num);           // 4.940656458412465e-324
}


DBL_MIN não é um duplo positivo mínimo.

 
fxsaber:

DBL_MIN é um duplo positivo não-mínimo.

Penso que o segundo número tem um formato duplo inválido, mas ainda é validado tanto na impressora como nas operações.

 
fxsaber:
Não o recebi aqui.


DBL_MIN não é um duplo positivo mínimo.

Bem, compare DBL_MIN com NaN - o resultado será em bool, certo?

E se dividirmos 1.0 por um número não-número, obteremos uma excepção, como foi dito acima

em geral, o facto de os criadores terem escrito muitas vezes que comparar com mais/menos do que/igual ao dobro não é correcto - é verdade, por vezes é possível obter um não-número e o resultado da comparação não será previsível.