汎用クラスライブラリ - バグ、説明、質問、使用上の特徴、提案

 

2017年12月6日以降、MetaTrader 5の 標準配信には、データの保存と検索のための効率的なアルゴリズムを実装する、いわゆるGeneric クラスが含まれています。このスレッドは、これらのクラス、それらを使用した例、およびそれらの動作を改善するための提案について説明するために作成されています。

ジェネリッククラスとは? ジェネリッククラスは カスタムデータ型を 格納できる特別なテンプレートクラスです。型の識別はコンパイル時に行われるため、高いパフォーマンスが得られます。

なぜジェネリックなのか? 原則として、初心者のプログラマーは1つのコレクション型、つまり配列しか知りません。しかし、配列を扱うのが非効率的なタスクはたくさんある。例えば、100万個のユニークな識別子からなる配列があるとします。この1,000件の注文の中に、番号Nの注文が1件あるかどうかを調べるにはどうすればいいでしょうか?ジェネリック・クラスの一つを使えば、このタスクはほとんど瞬時に、しかも探索の対象となる要素の数に依存しない一定の時間で実行できる。プログラマが考案したアルゴリズムよりも、ジェネリックコレクションの正しいアルゴリズムの方が速いタスクは他にもあります。

汎用アルゴリズム。 以下はジェネリッククラスの表で、それらが何をするのかを簡単に説明しています:

クラス説明
CArrayList.自動サイズ分割機能を持つ配列。配列の外に出ることを制御することなく、配列を利用できる。
CHashMapキー・バリュー・セット。キーによる要素の効率的な挿入、取得、検索を可能にする。キーは一意でなければならない。例えば、CHashMap は、指定された番号の注文を即座に検索することができます。
CHashSet一意な要素の集合。CHashMap と同じことができますが、キーは必要ありません。このコレクションに格納される要素は、繰り返されてはならない。また、項目の検索、取得、追加を即座に行うことができます。
CLinkedList二重リンクリスト。項目の挿入と削除が簡単にできる。しかし、目的の項目を見つけるのに、リスト内の項目数に線形に依存する時間がかかる。
CQueueヒープ。FIFO型のキューを整理する。
CStackスタック。LIFO型のキューを整理する
CRedBlackTreeRedBlackTree。要素の挿入、抽出、検索を(対数時間で)高速に行うことができる。CHashMapやCHashSetとは異なり、more than、less than、betweenなどの 追加的な関係アルゴリズムを効率的に実装することができる。
CSortedMapキーでソートされた集合。キーと値の値を格納する。この場合、キーはソートされる。
CSortedSet値による並べ替えセット。並べ替えられた値の集合を格納する。

後で、これらのクラスの実装機能を見ていく。

 
ワシリー・ソコロフ

例えば1000件の注文など、100万件の一意な識別子の配列があるとします。1000件の注文の中に、番号Nの注文が1件あるかどうかを確認するにはどうしたらよいでしょうか。汎用クラスの一つを使えば、この作業はほぼ瞬時に、検索する要素の 数に依存しない一定の時間で達成される。

全く詳しくない。しかし、強調された部分は非論理的に聞こえます。

 

残念ながら、ライブラリは発売されたばかりで、まだ生ものです。すでにその中の最初のエラーを発見しています(マーカーでエラーを強調します)。

CSortedSet でエラーが発生しました。

//+------------------------------------------------------------------+
//| Class CSortedSet<T>.                                             |
//| Usage: Represents a collection of objects that is maintained in  |
//|        sorted order.                                             |
//+------------------------------------------------------------------+
template<typename T>
class CSortedSet: public ISet<T>
  {
   ...
   bool              TryGetMin(T &min)    { return(m_tree.TryGetMin(min)); }
   bool              TryGetMax(T &max)    { return(m_tree.TryGetMin(max)); }
   ...
  }

TryGetMaxメソッドは、TryGetMinメソッドと同様に、最大要素の代わりに最小要素を返します。

 
fxsaber

...しかし、強調された部分は非論理的に聞こえます。

それはなぜでしょうか?

 
ワシリー・ソコロフ

それはなぜでしょうか?

ハッシュを作り、昇順に並べる。しかし、いずれにせよ捜索は行われるでしょう。

 
fxsaber

全く詳しくない。しかし、強調された部分は非論理的に聞こえます。

平均時間 O(1) 最悪 O(n) であり、性能はハッシュに大きく依存する。
 
fxsaber

ハッシュを作る ...

用語を定義しておこう。瞬間的なものはない。どんな操作にも時間がかかる。瞬間的と 言ったのは、初心者のプログラマーにもわかるように単純化しているんです。厳密には、複雑さにはいくつかのクラスが ありますが、これから扱う主なものは以下の通りです。

  • 一定の複雑さcO(1)。
  • 対数:cO(log n)です。
  • リニア:cO (n)。
  • 非線形ランタイムを必要とするアルゴリズム。

ハッシュ値の計算など、技術的な操作の際に発生する定数のようなもので、あえてc 記号を導入しました。しかし、この場合、定数cの 最適化の議論は、このスレッドの主題から外れています。ここでは、一般的なクラスとその実際の適用にのみ興味があります。

 
fxsaber

ハッシュを作り、昇順に並べる。しかし、いずれにせよ検索は行われるでしょう。

コンビナート です。
平均時間 O(1) 最悪 O(n) で、性能はハッシュに大きく依存する。

+

p.s. 説明のために、CHashMapを正しく扱わないと、これと同じ性能がO(n)に落ちてしまう例を示します。

 
ワシリー・ソコロフ

とてもわかりやすく書いていただきました。

ハイライトされているものを見てください。

 

名前をもっとシンプルに、論理的にしたほうがいい。例えば、CArrayListは Arrayなのか、mql5におけるListなのか、両方の実装なのか。

そのため、疑問や混乱が生じるのです。IMHOは、C#やJavaではなく、stlを使うべきだと考えています。あるいは、前のCを削除して、ArrayListだけにしてください。


普通の名前を作れば。

- 読みやすさが何倍にもなります。

- あなただけのmql5スタイルができあがります。

- 初心者の方でもすぐに操作できるようになります(stlが標準装備されているため)

 
ワシリー・ソコロフ

...

例えば、何千もの案件の中から検索するような例を挙げていただければと思います。