Librerías: Math Utils - página 2

 
Actualización 21 febrero 2023

Añadida una nueva función para comparar dobles:

//+------------------------------------------------------------------+
//| Prueba si dos números están cerca dentro de "n" significativos |
//| dígitos de precisión.|
//+------------------------------------------------------------------+
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 #:
Añadidas dos nuevas funciones para comparar dobles:

Más 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 #:

Más rápido.

Feo.

Claro, es más rápido pero en lenguajes interpretados como JavaScript, pero no en MQL. Ver https://stackover flow.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));
  }

// IgualesDobles(1.2345,5.4321,4) -> 0 mseg
// EqualDoubles_2(1.2345,5.4321,4) -> 0 mseg
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, es más rápido pero en lenguajes interpretados como JavaScript, pero no en MQL. Véase https://stackoverflow.com/a/48764436.

Tienes que aprender a hacer mediciones de rendimiento adecuadas.

#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 veces más rápido.

 

@fxsaber Sí, tienes razón, me olvidé de que la expresión fue optimizado a cabo, coz su valor no fue utilizado.

Sin embargo, el mío tarda 0,04 microseg por llamada. ¿Crees que vale la pena esta micro-optimización sobre la legibilidad?

El porcentaje ahorrado sobre todo un programa = porcentaje función se llama * porcentaje ahorrado por la optimización.

Seguramente, el primer término de la ecuación es siempre demasiado pequeño para esta función específica. Es por eso que el perfil de su programa es a veces más importante para ver el cuadro completo, en lugar de cronometrar una sola instrucción.

Gracias por pasarte por aquí :-)
 
amrali #:

Sin embargo, el mío tarda 0,04 microseg por llamada. ¿Crees que vale la pena esta micro-optimización por encima de la legibilidad?

En este caso, estoy definitivamente del lado del rendimiento. La legibilidad es muy fácil para mí.

 
fxsaber #:

En este caso, estoy definitivamente del lado del rendimiento. La legibilidad es muy fácil para mí.

Seguro que sí. Cuídate.

 
Print(EqualDoubles(1.2345, 5.4321, 0)); // verdadero
 
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
 

Me parece que tal modificación de la condición es correcta.

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