ライブラリ: 数学ユーティリティ - ページ 2

 
2023年2月21日更新

倍数の比較関数を追加:

//+------------------------------------------------------------------+
//| 2つの数値が有効数字 "n "以内に近いかどうかをテストする。
//| 精度の桁数。|
//+------------------------------------------------------------------+
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 #:
ダブルを比較する2つの関数を追加:

より速く。

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

もっと速く。

醜い!

確かに、JavaScriptのようなインタプリタ型言語では速くなるが、MQLではそうはいかない。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ミリ秒
// EqualDoubles_2(1.2345,5.4321,4) -> 0ミリ秒
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 #:

確かに、JavaScriptのようなインタプリタ型言語では速くなるが、MQLではそうはいかない。https://stackoverflow.com/a/48764436。

適切なパフォーマンス測定の方法を学ぶ必要がある。

#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倍速い。

 

はい、その通りです。式が最適化されるのを忘れていました。

しかし、私のは1回の呼び出しに0.04マイクロ秒かかります。可読性よりもこの微小最適化に価値があると思いますか?

プログラム全体で節約されたパーセンテージ = 関数が呼び出されたパーセンテージ * 最適化によって節約されたパーセンテージ。

確かに、方程式の第1項は、この特定の関数にとっては常に小さすぎる。だから、プログラムをプロファイリングすることは、1つの命令のタイミングを計ることよりも、全体像を見ることの方が重要なのです。

お立ち寄りいただきありがとうございました。)
 
amrali #:

しかし、私のは1回の呼び出しに0.04マイクロ秒かかる。読みやすさよりもこのマイクロ最適化に価値があると思いますか?

この場合、私は間違いなくパフォーマンス側です。可読性は私にとって非常に簡単です。

 
fxsaber #:

この場合、私は間違いなくパフォーマンス側だ。可読性は私にとって非常に簡単だ。

お気をつけて。

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

私には、このような条件の変更は正しいと思える。

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