Libraries: Math Utils - page 3

 
@fxsaber NormalizeDouble rounds to decimal places, which is different from rounding to significant digits. SF is 1-15 or 17 inclusive. There is no 0.
 
amrali #:
@fxsaber NormalizeDouble rounds to decimal places, which is different from rounding to significant digits. SF is 1-15 or 17 inclusive. There is no 0.

Didn't understand.

 

NormalizeDouble(12.345, 2) -> 12.35

RoundToSignificantDigits(12.345, 2) -> 12


EqualDouble() is used to compare suspected equal amounts like 1.123456 and 1.23456789

also can be used very large numbers like 1234567891234.1234 and  1234567891234.1255

without knowing the decimal digits in the numbers you comapre against each other.
 
It looks like I understand the term "significant digits of precision" differently.
 
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 on trading, automated trading systems and testing trading strategies

Libraries: Math Utils

fxsaber, 2023.02.21 21:01

You need to learn how to make proper performance measurements.

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

#define BENCH(A) for (int i = 0; i < 1e8; 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 times faster.


@fxsaber I did not check after you, yesterday!

But, when I came back today, I found you benchmarked it wrongly. You just benchmarked the modulo % operator, but with some compiler's internal optimizations you got that unrealistic difference.

I used this simple benchmark to re-check. Both functions are fast enough. So, no change!

#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 to avoid optimizing expression out.
   int runs = 1e8;

   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 I did not check after you, yesterday!

But, when I came back today, I found you benchmarked it wrongly. You just benchmarked the modulo % operator, but with some compiler's internal optimizations you got that unrealistic difference.

I used this simple benchmark to re-check. Both functions are fast enough. So, no change!

You are drawing wrong conclusions.

   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

means the function calls were not optimized by the compiler. I do not know why you manipulate the 3rd argument, leave it as a default parameter and re-test.

Use a simple loop.

void OnStart()
  {
   double sum = 0; // use double to avoid optimizing expression out.
   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 #:

means the function calls were not optimized by the compiler. I do not know why you manipulate the 3rd argument, leave it as a default parameter and re-test.

Use a simple loop.

Unfortunately, you do not understand what you are measuring.

Disable compiler optimizations and give it a try.


 

So, why to disable? I write the function, then I depend on the optimizing compiler.

Otherwise, I would program in assembly like in the old days :-)