Библиотеки: Math Utils - страница 3

 
@fxsaber NormalizeDouble округляет до десятичных знаков, что отличается от округления до значащих цифр. SF - это 1-15 или 17 включительно. 0 не существует.
 
amrali #:
@fxsaber NormalizeDouble округляет до десятичных знаков, что отличается от округления до значащих цифр. SF - это 1-15 или 17 включительно. 0 не существует.

Не понял.

 

NormalizeDouble(12.345, 2) -> 12.35

RoundToSignificantDigits(12.345, 2) -> 12


EqualDouble() используется для сравнения подозрительных равных сумм, например 1.123456 и 1.23456789.

также может использоваться для сравнения очень больших чисел, таких как 1234567891234.1234 и 1234567891234.1255.

не зная десятичных цифр в числах, которые вы сравниваете друг с другом.
 
Похоже, я по-разному понимаю термин "значимые цифры точности".
 
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...
 

Форум о трейдинге, автоматизированных торговых системах и тестировании торговых стратегий

Библиотеки: Math Utils

fxsaber, 2023.02.21 21:01

Вам нужно научиться делать правильные замеры производительности.

#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 раз быстрее.


@fxsaber Я не проверил после вас, вчера!

Но, когда я вернулся сегодня, я обнаружил, что вы сделали бенчмарк неправильно. Вы просто проверили оператор modulo %, но с помощью внутренних оптимизаций компилятора получили нереальную разницу.

Я использовал этот простой бенчмарк для повторной проверки. Обе функции работают достаточно быстро. Так что никаких изменений!

#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, чтобы не оптимизировать выражение.
   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 миллисекунд
// sum1+=EqualDoubles_v2(1.12345,1.12345) -> 125 миллисекунд
// 200000000.0
 
amrali #:

@fxsaber Я не проверил после вас, вчера!

Но, вернувшись сегодня, я обнаружил, что вы неправильно провели бенчмарк. Вы просто проверили оператор modulo %, но благодаря внутренним оптимизациям компилятора получили нереальную разницу.

Я использовал этот простой бенчмарк для повторной проверки. Обе функции работают достаточно быстро. Так что никаких изменений!

Вы делаете неверные выводы.

   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

означает, что вызовы функций не были оптимизированы компилятором. Я не знаю, зачем вы манипулируете 3-м аргументом, оставьте его в качестве параметра по умолчанию и протестируйте заново.

Используйте простой цикл.

void OnStart()
  {
   double sum = 0; // используйте double, чтобы не оптимизировать выражение.
   uint t1 = GetTickCount();
   for (int i = 0; i < runs; ++i)
   {
    sum += !EqualDoubles(1.12345, 5.12345);
   }
   Print("EqualDoubles -> ", GetTickCount() - t1, " msec");  // 109 мс
   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 мс
   Print(sum);
  }
 
amrali #:

означает, что вызовы функций не были оптимизированы компилятором. Я не знаю, зачем вы манипулируете 3-м аргументом, оставьте его в качестве параметра по умолчанию и протестируйте заново.

Используйте простой цикл.

К сожалению, вы не понимаете, что измеряете.

Отключите оптимизацию компилятора и попробуйте.


 

Так зачем отключать? Я пишу функцию, а потом завишу от оптимизирующего компилятора.

Иначе я бы программировал на ассемблере, как в старые добрые времена :-)