Bibliotecas: Math Utils - página 3

 
@fxsaber NormalizeDouble arredonda para casas decimais, o que é diferente de arredondar para dígitos significativos. SF é 1-15 ou 17 inclusive. Não há 0.
 
amrali #:
@fxsaber NormalizeDouble arredonda para casas decimais, o que é diferente de arredondar para dígitos significativos. SF é 1-15 ou 17 inclusive. Não há 0.

Não entendi.

 

NormalizeDouble(12.345, 2) -> 12.35

RoundToSignificantDigits(12.345, 2) -> 12


EqualDouble() é usado para comparar valores suspeitos de serem iguais, como 1,123456 e 1,23456789

também pode ser usado com números muito grandes, como 1234567891234.1234 e 1234567891234.1255

sem conhecer os dígitos decimais dos números que você compara entre si.
 
Parece que estou entendendo o termo "dígitos significativos de precisão" de forma diferente.
 
Wikiwand - Significant figures
  • www.wikiwand.com
Significant figures (also known as the significant digits , precision or resolution ) of a number in positional notation are digits in the number that are reliable and necessary to indicate the quantity of something. If a number expressing the result of a measurement (e.g., length, pressure, volume, or mass) has more digits than the number of...
 

Fórum sobre negociação, sistemas de negociação automatizados e teste de estratégias de negociação

Bibliotecas: Utilitários matemáticos

fxsaber, 2023.02.21 21:01

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 Eu não verifiquei depois de você, ontem!

Mas, quando voltei hoje, descobri que você fez o benchmarking de forma errada. Você só fez o benchmark do operador de módulo %, mas com algumas otimizações internas do compilador você obteve essa diferença irreal.

Usei esse benchmark simples para verificar novamente. Ambas as funções são suficientemente rápidas. Portanto, nenhuma mudança!

#define  Benchmark(runs, expression)                                  \
do {                                                                 \
   uint t0 = GetTickCount();                                         \
   for (int i = 0; i < (runs); ++i) { (expression); }                \
   printf("%s -> %I64d millisec", #expression, GetTickCount() - t0); \
} while(0)
//+------------------------------------------------------------------+
void OnStart()
  {
   double sum1 = 0; // use double para evitar a otimização da expressão.
   int runs = 1 e8;

   Benchmark(runs, sum1 += EqualDoubles(1.12345, 1.12345));
   Benchmark(runs, sum1 += EqualDoubles_v2(1.12345, 1.12345));
   Print(sum1);
  }
//+------------------------------------------------------------------+
// sum1+=EqualDoubles(1.12345,1.12345) -> 110 milisseg
// sum1+=EqualDoubles_v2(1.12345,1.12345) -> 125 milisseg
// 200000000.0
 
amrali #:

@fxsaber Eu não verifiquei depois de você, ontem!

Mas, quando voltei hoje, descobri que você fez o benchmarking de forma errada. Você apenas comparou o operador de módulo %, mas com algumas otimizações internas do compilador você obteve essa diferença irreal.

Usei esse benchmark simples para verificar novamente. Ambas as funções são suficientemente rápidas. Portanto, nenhuma mudança!

Você está tirando conclusões erradas.

   Benchmark(runs, sum1 += EqualDoubles(1.2345, 5.4321, i ? 10 : 15));
   Benchmark(runs, sum1 += EqualDoubles_v2(1.2345, 5.4321, i ? 10 : 15));
sum1+=EqualDoubles(1.2345,5.4321,i?10:15) -> 4140 millisec
sum1+=EqualDoubles_v2(1.2345,5.4321,i?10:15) -> 110 millisec
 
// 200000000.0

significa que as chamadas de função não foram otimizadas pelo compilador. Não sei por que você manipula o terceiro argumento, deixe-o como um parâmetro padrão e teste novamente.

Use um loop simples.

void OnStart()
  {
   double sum = 0; // use double para evitar a otimização da expressão.
   uint t1 = GetTickCount();
   for (int i = 0; i < runs; ++i)
   {
    sum += !EqualDoubles(1.12345, 5.12345);
   }
   Print("EqualDoubles -> ", GetTickCount() - t1, " msec");  // 109 mseg
   Print(sum);

   uint t2 = GetTickCount();
   for (int i = 0; i < runs; ++i)
   {
    sum += !EqualDoubles_v2(1.12345, 5.12345);
   }
   Print("EqualDoubles -> ", GetTickCount() - t2, " msec");  // 125 mseg
   Print(sum);
  }
 
amrali #:

significa que as chamadas de função não foram otimizadas pelo compilador. Não sei por que você manipula o terceiro argumento, deixe-o como um parâmetro padrão e teste novamente.

Use um loop simples.

Infelizmente, você não entende o que está medindo.

Desative as otimizações do compilador e tente novamente.


 

Então, por que desativar? Eu escrevo a função e depois dependo do compilador de otimização.

Caso contrário, eu programaria em assembly como nos velhos tempos :-)