Bibliotheken: Math Utils - Seite 3

 
@fxsaber NormalizeDouble rundet auf Dezimalstellen, was sich von der Rundung auf signifikante Stellen unterscheidet. SF ist 1-15 oder 17 einschließlich. Es gibt keine 0.
 
amrali #:
@fxsaber NormalizeDouble rundet auf Dezimalstellen, was sich von der Rundung auf signifikante Stellen unterscheidet. SF ist 1-15 oder 17 einschließlich. Es gibt keine 0.

Das habe ich nicht verstanden.

 

NormalizeDouble(12,345, 2) -> 12,35

RoundToSignificantDigits(12.345, 2) -> 12


EqualDouble() wird verwendet, um mutmaßlich gleiche Beträge wie 1.123456 und 1.23456789 zu vergleichen.

kann auch für sehr große Zahlen wie 1234567891234.1234 und 1234567891234.1255 verwendet werden

ohne die Dezimalstellen der Zahlen zu kennen, die man miteinander vergleicht.
 
Es sieht so aus, als würde ich den Begriff "signifikante Stellen der Genauigkeit" anders verstehen.
 
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...
 

Forum zum Thema Handel, automatisierte Handelssysteme und Testen von Handelsstrategien

Bibliotheken: Math Utils

fxsaber, 2023.02.21 21:01

Du musst lernen, wie man richtige Leistungsmessungen durchführt.

#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 Ich habe gestern nicht nach Ihnen geschaut!

Aber als ich heute zurückkam, habe ich festgestellt, dass du den Benchmark falsch durchgeführt hast. Du hast nur den modulo %-Operator gemessen, aber mit einigen compilerinternen Optimierungen hast du diesen unrealistischen Unterschied erhalten.

Ich habe diesen einfachen Benchmark verwendet, um ihn erneut zu überprüfen. Beide Funktionen sind schnell genug. Also, keine Änderung!

#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; // double verwenden, um die Optimierung des Ausdrucks zu vermeiden.
   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 millisec
// sum1+=EqualDoubles_v2(1.12345,1.12345) -> 125 millisec
// 200000000.0
 
amrali #:

@fxsaber Ich habe nicht nach Ihnen gesehen, gestern!

Aber als ich heute zurückkam, stellte ich fest, dass du den Benchmark falsch durchgeführt hast. Du hast nur den modulo %-Operator gemessen, aber mit einigen compilerinternen Optimierungen hast du diesen unrealistischen Unterschied erhalten.

Ich habe diesen einfachen Benchmark verwendet, um ihn erneut zu überprüfen. Beide Funktionen sind schnell genug. Also, keine Änderung!

Sie ziehen falsche Schlüsse.

   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

bedeutet, dass die Funktionsaufrufe vom Compiler nicht optimiert wurden. Ich weiß nicht, warum Sie das 3. Argument manipulieren, lassen Sie es als Standardparameter und testen Sie es erneut.

Verwenden Sie eine einfache Schleife.

void OnStart()
  {
   double sum = 0; // double verwenden, um die Optimierung des Ausdrucks zu vermeiden.
   uint t1 = GetTickCount();
   for (int i = 0; i < runs; ++i)
   {
    sum += !EqualDoubles(1.12345, 5.12345);
   }
   Print("EqualDoubles -> ", GetTickCount() - t1, " msec");  // 109 msec
   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 msec
   Print(sum);
  }
 
amrali #:

bedeutet, dass die Funktionsaufrufe vom Compiler nicht optimiert wurden. Ich weiß nicht, warum Sie das 3. Argument manipulieren, lassen Sie es als Standardparameter und testen Sie es erneut.

Verwenden Sie eine einfache Schleife.

Leider verstehen Sie nicht, was Sie messen.

Deaktivieren Sie die Compiler-Optimierungen und versuchen Sie es erneut.


 

Warum also deaktivieren? Ich schreibe die Funktion, dann bin ich auf den optimierenden Compiler angewiesen.

Sonst würde ich in Assembler programmieren, wie in den alten Zeiten :-)