Bibliotheken: Math Utils - Seite 2

 
Aktualisierung 21. Februar 2023

Neue Funktion für den Vergleich von Doppeln hinzugefügt:

//+------------------------------------------------------------------+
//| Testen, ob zwei Zahlen innerhalb von "n" signifikanten Punkten liegen
//| Stellen der Genauigkeit.|
//+------------------------------------------------------------------+
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 #:
Zwei neue Funktionen für den Vergleich von Doppeln hinzugefügt:

Schneller.

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 #:

Schneller.

Hässlich!

Sicher, es ist schneller, aber in interpretierten Sprachen wie JavaScript, aber nicht in MQL. Siehe 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 #:

Sicher, es ist schneller, aber in interpretierten Sprachen wie JavaScript, aber nicht in MQL. Siehe https://stackoverflow.com/a/48764436.

Sie müssen lernen, wie man richtige Leistungsmessungen vornimmt.

#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 Mal schneller.

 

@fxsaber Ja, du hast Recht, ich habe vergessen, dass der Ausdruck optimiert wurde, weil sein Wert nicht verwendet wurde.

Meiner braucht jedoch 0,04 Mikrosekunden pro Aufruf. Denken Sie, dass es diese Mikro-Optimierung über die Lesbarkeit wert?!

Der eingesparte Prozentsatz über ein ganzes Programm = Prozentsatz Funktion wird aufgerufen * Prozentsatz durch Optimierung eingespart.

Sicherlich ist der 1. Term der Gleichung immer viel zu klein für diese spezielle Funktion. Deshalb ist es manchmal wichtiger, ein Programm zu profilieren, um das Gesamtbild zu sehen, als eine einzelne Anweisung zu messen.

Danke, dass Sie vorbeigekommen sind :-)
 
amrali #:

Meiner braucht jedoch 0,04 Mikrosekunden pro Aufruf. Glauben Sie, es lohnt sich diese Mikro-Optimierung über Lesbarkeit?!

In diesem Fall bin ich definitiv auf der Seite der Leistung. Die Lesbarkeit ist für mich sehr einfach.

 
fxsaber #:

In diesem Fall stehe ich eindeutig auf der Seite der Leistung. Die Lesbarkeit ist für mich sehr einfach.

Da bin ich mir sicher. Machen Sie es gut.

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

Meines Erachtens ist eine solche Änderung der Bedingung korrekt.

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