程序库: 数学工具 - 页 3

 
@fxsaber NormalizeDouble 四舍五入到小数位,这与四舍五入到有效数字不同。SF 是 1-15 或 17(包括 17)。没有 0。
 
amrali #:
@fxsaber NormalizeDouble 四舍五入到小数位,这与四舍五入到有效数字不同。SF 是 1-15 或 17(包括 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...
 

关于交易、自动交易系统和交易策略测试的论坛

图书馆:数学工具

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 个参数,请将其保留为默认参数并重新测试。

使用一个简单的循环。

不幸的是,你不知道自己在测量什么。

禁用编译器优化,然后再试试。


 

那么,为什么要禁用呢?我写了函数,然后依赖优化编译器。

否则,我就会像以前一样用汇编程序编程 :-)