Bibliotecas: Math Utils - página 2

 
Atualização 21 de fevereiro de 2023

Adicionada uma nova função para comparação de duplas:

//+------------------------------------------------------------------+
//| Teste se dois números estão próximos dentro de "n" significantes
//| dígitos de precisão.|
//+------------------------------------------------------------------+
bool EqualDoubles(const double a, const double b, const int significantDigits = 15)
  {
//--- https://stackoverflow.com/a/17382806
   return MathAbs(a - b) < MathPow(10, -significantDigits) * MathMax(MathAbs(a), MathAbs(b));
  }
 
amrali #:
Foram adicionadas duas novas funções para comparação de duplas:

Mais rápido.

bool EqualDoubles(const double a, const double b, const int significantDigits = 15)
  {
    static const double MathPows[] = {1 e-0, 1 e-1, 1 e-2, 1 e-3, 1 e-4, 1 e-5, 1 e-6, 1 e-7, 1 e-8, 1 e-9, 1 e-10, 1 e-11, 1 e-12, 1 e-13, 1 e-14, 1 e-15};

//--- https://stackoverflow.com/a/17382806
   return MathAbs(a - b) < MathPows[significantDigits] * MathMax(MathAbs(a), MathAbs(b));
  }
 
fxsaber #:

Mais rápido.

Feio!

Claro, é mais rápido, mas em linguagens interpretadas como JavaScript, mas não em MQL. Consulte https://stackoverflow.com/a/48764436.

void OnStart()
  {
   int runs = 1 e9;
   Benchmark(runs, EqualDoubles(1.2345, 5.4321, 4));
   Benchmark(runs, EqualDoubles_2(1.2345, 5.4321, 4));
  }

// EqualDoubles(1.2345,5.4321,4) -> 0 msec
// EqualDoubles_2(1.2345,5.4321,4) -> 0 msec
How to round to at most 2 decimal places, if necessary
How to round to at most 2 decimal places, if necessary
  • 2012.08.06
  • stinkycheeseman stinkycheeseman 42.2k 7 7 gold badges 29 29 silver badges 49 49 bronze badges
  • stackoverflow.com
I'd like to round at most two decimal places, but only if necessary . How can I do this in JavaScript?
 
amrali #:

É claro que é mais rápido, mas em linguagens interpretadas como JavaScript, mas não em MQL. Consulte https://stackoverflow.com/a/48764436.

Você precisa aprender a fazer medições de desempenho adequadas.

#include <fxsaber\Benchmark\Benchmark.mqh> // https://www.mql5.com/ru/code/31279

#define  BENCH(A) for (int i = 0; i < 1 e8; i++) Tmp += A

void OnStart ()
{
  int Tmp = 0;  
  _BV(BENCH(EqualDoubles(1.2345, 5.4321, i % 15)), 1) // 3953430 mcs.
  Print(Tmp);
  
  Tmp = 0;
  _BV(BENCH(EqualDoubles2(1.2345, 5.4321, i % 15)), 1) // 182654 mcs.
  Print(Tmp);  
}

21 vezes mais rápido.

 

@fxsaber Sim, você está certo, esqueci que a expressão foi otimizada, pois seu valor não foi usado.

No entanto, o meu leva 0,04 microsseg por chamada. Você acha que vale a pena essa micro-otimização em detrimento da legibilidade?

A porcentagem economizada em um programa inteiro = a função de porcentagem é chamada * porcentagem economizada pela otimização.

Certamente, o primeiro termo da equação é sempre muito pequeno para essa função específica. É por isso que, às vezes, a criação de perfil do seu programa é mais importante para ver o quadro completo, em vez de cronometrar uma única instrução.

Obrigado por sua visita :-)
 
amrali #:

No entanto, o meu leva 0,04 microsseg por chamada. Você acha que vale a pena essa micro-otimização em detrimento da legibilidade?

Nesse caso, estou definitivamente do lado do desempenho. A legibilidade é muito fácil para mim.

 
fxsaber #:

Nesse caso, estou definitivamente do lado do desempenho. A legibilidade é muito fácil para mim.

Tenho certeza de que você também é. Tome cuidado.

 
Print(EqualDoubles(1.2345, 5.4321, 0)); // verdadeiro
 
bool EqualDoubles3( const double a, const double b, const int significantDigits = 8 )
  {
   return(!NormalizeDouble(a - b, significantDigits));
  }
Alert: Bench_Stack = 0, 1 <= Time[Test5-3.mq5 169 in OnStart: for(inti=0;i<1 e8;i++)Tmp+=EqualDoubles(1.2345,5.4321,i%8)] = 3689020 mcs.
12500000
Alert: Bench_Stack = 0, 1 <= Time[Test5-3.mq5 173 in OnStart: for(inti=0;i<1 e8;i++)Tmp+=EqualDoubles2(1.2345,5.4321,i%8)] = 111013 mcs.
12500000
Alert: Bench_Stack = 0, 1 <= Time[Test5-3.mq5 177 in OnStart: for(inti=0;i<1 e8;i++)Tmp+=EqualDoubles3(1.2345,5.4321,i%8)] = 573889 mcs.
0
 

Parece-me que essa modificação da condição está correta.

bool EqualDoubles4(const double a, const double b, const int significantDigits = 15)
  {
//--- https://stackoverflow.com/a/17382806
   return (a == b) || (MathAbs(a - b) < MathPow(10, -significantDigits) * MathMax(MathAbs(a), MathAbs(b)));
  }