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

 

以下は、そのコードと入力フィールド です。(誰かにとって便利かもしれない。 洗練されることもある)。

//+------------------------------------------------------------------+
//|                                                   Dictionary.mq5 |
//|                                                      Peter Konow |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Peter Konow"
#property link      ""
#property version   "1.00"
#property strict
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
#define  Max_possible_collisions    100
#define  Max_letters_in_word        100
#define  All_letters_in_alphabet    255 
//------------------------------------
string Dictionary[Max_possible_collisions][All_letters_in_alphabet][Max_letters_in_word];
//-------------------------------------------------------------------
int OnInit()
  {
//---
   Create_text_box();
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   ObjectDelete(0,"Text_box");
  }
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
    if(id == CHARTEVENT_OBJECT_ENDEDIT)
      { 
       //-----------------------
       string Text;     
       //---------------------
       ObjectGetString(0,"Text_box",OBJPROP_TEXT,0,Text);
       //-------------------------------------
       Add(Text);
      } 
  }
//+------------------------------------------------------------------+

void Add(string word)
{
 uchar First_letter = (uchar)StringGetCharacter(word,0) - 97;
 //-----------------------
 int All_letters_in_word = StringLen(word);
 //-----------------------
 for(int a1 = 0; a1 < Max_possible_collisions; a1++)
   {
     string word_inside = Dictionary[a1][First_letter][All_letters_in_word];
     //-----------------------   
    if(word_inside == NULL)
      {
       Dictionary[a1][First_letter][All_letters_in_word] = word;
       Print("Your word has been added to our dictionary!");
       break;
      }
    if(word_inside == word)
      {
       Print("This word already exists in our dictionary");
       break;
      } 
   }   
 //------------------------   
}
//--------------------------------------------------------------------+


//--------------------------------------------------------------------
void Create_text_box()
{
  ObjectCreate(0,"Text_box",OBJ_EDIT,0,0,0);
  ObjectSetInteger(0,"Text_box",OBJPROP_XDISTANCE,500);
  ObjectSetInteger(0,"Text_box",OBJPROP_YDISTANCE,250);
  ObjectSetInteger(0,"Text_box",OBJPROP_XSIZE,400);
  ObjectSetInteger(0,"Text_box",OBJPROP_YSIZE,30);
  ObjectSetString(0,"Text_box",OBJPROP_TEXT,"Please enter your word here...");
  ObjectSetString(0,"Text_box",OBJPROP_FONT,"TimesNewRoman");
  ObjectSetInteger(0,"Text_box",OBJPROP_STATE,1);
  //----------------------------------------------
  ObjectSetInteger(0,"Text_box",OBJPROP_FONTSIZE,12);
  ObjectSetInteger(0,"Text_box",OBJPROP_BGCOLOR,clrWhite);
  ObjectSetInteger(0,"Text_box",OBJPROP_COLOR,clrBlack);
  ObjectSetInteger(0,"Text_box",OBJPROP_BORDER_COLOR,clrBlack);
  ObjectSetInteger(0,"Text_box",OBJPROP_ALIGN,ALIGN_CENTER);
  //----------------------------------------------
  ObjectSetInteger(0,"Text_box",OBJPROP_CORNER,CORNER_LEFT_UPPER);
  ObjectSetInteger(0,"Text_box",OBJPROP_ANCHOR,ANCHOR_LEFT_UPPER);  
  //---------------------------------------------- 
}
//----------------------------------------------------------------------- 

ただ、なぜか4号機では完全に動作します。5番目は、フィールドが表示されない。その理由を探したが見つからなかった。

 
fxsaber:

つまり、タスクごとに、辞書のサイズ(RAM)とハッシュ関数の計算量(CPU)の適切なバランスを見つける必要があるのです。


比較的そうですね。
要素数が少ない場合、辞書の最適サイズは要素数の2乗となる(3年前の講習で覚えた範囲だが、常に再確認した方が良い)。
要素数が多く、最適なサイズを選択できない場合は、想定要素数の数倍の辞書サイズをとり、衝突ごとに内部ハッシュテーブルを使用するなど、衝突処理を最適化する。

ハッシュテーブルは、できるだけ高速に検索され、なおかつ単語リストのサイズに対して得られる結果の分布が一様に なるように選択することが試みられている。
ハッシュに素数を使うのは、分布の一様性に関係する。

 
Konow tag:
大文字はコードが異なり、配列から "脱落 "するため、配列サイズを大きくする必要がありました。

のコードと "a "文字のコードはちょうど32だけ異なる。これに対応して、残りもすべて32の差があります。

配列のサイズを 大きくせず、1文字目を置き換えるべきだったかもしれません。
 
Alexey Viktorov:

文字 "A "のコードは、文字 "a "のコードとちょうど32だけ異なっている。したがって、それ以外もすべて差分32となる。

配列のサイズを大きくせず、1文字目を置き換えるべきだったかもしれません。

私もそう思います。この点については、アルゴリズムが不完全である。

アレイのサイズが 大きすぎる。昨日は文字コードを理解しきれなかった。

 
タグコノウ

以下は、そのコードと入力フィールド です。(誰かにとって便利かもしれない。洗練させることができる)。

しかし、4では全く問題なく動作します。5にフィールドが表示されない。その理由を探したが、見つからなかった。

もう一つ、Vasiliy の例では、配列

トレーディング、自動売買システム、ストラテジーテストに関するフォーラム

汎用クラスライブラリ - エラー、説明、質問、使用上の特殊性、提案

ヴァシリー・ソコロフ さん 2017.12.07 14:30

連想配列で非常にシンプル #1

Genericで紹介されているアルゴリズムには、連想配列や辞書を利用したものが非常に多くあります。また、最もよく使われる2つのアルゴリズムのうちの1つです。プログラミングの作業の9割は、配列と辞書でカバーされていると言っても過言ではないでしょう。実践に移る前に、辞書の働きをできるだけわかりやすく、意図的に細部を簡略化して説明しよう。

ここでは、非常に簡単な例として、通常の単語リストで辞書を紹介する。例えば、アルファベットで始まる単語がいくつかあるとします。

string words[] = {"apple", "cat", "fog", "dog", "walk", "zero"};

英語のアルファベットは26文字です。サイズ26要素の文字列の配列を作成してみましょう。

string dictionary[26];

ここで、単語をその最初の文字に対応するインデックスに格納することに同意すれば、簡単な辞書ができあがる。ゼロからインデックスを作成します。単語「apple」は、文字「a」がアルファベットの最初の文字であるため、インデックス0に格納され、「cat」はインデックス1、「dog」はインデックス3、「fog」はインデックス4、「walk」はインデックス24、「0」は最後のインデックス25に格納されることになります。

なお、インデックス5~23は使用しません。こ れは メモリの無駄 遣いですが、例えば「walk」という単語が存在すればインデックス24に位置することが分かっているので、即座にアクセスすることができます。

最初の空の辞書を書いてみましょう。



そして、あなたの例では

#define  Max_possible_collisions    100
#define  Max_letters_in_word        100
#define  All_letters_in_alphabet    255 
//------------------------------------
string Dictionary[Max_possible_collisions][All_letters_in_alphabet][Max_letters_in_word];

3次元配列はどのくらいのメモリを消費するのでしょうか?次元を増やさなければならない場合は?

 
Alexey Viktorov:

もうひとつ、Vasiliyの例では、配列について言及しています。


そして、あなたの例では

3次元配列はどのくらいのメモリを消費するのでしょうか?また、次元数を増やさなければならない場合はどうするか?

アレイのサイズが 大きすぎるため。

1.単語の最大文字数は100文字までと決めています。これは明らかにやりすぎです。30に減らすことができた。

2.また、可能な文字数も過大であることが判明しました。できるだけいろいろなキャラクターのスペースを取ることにしました。削減できる。

3.最初の文字と単語の文字数で一致させる「衝突」の回数は100回に設定されています。これもやりすぎです。50までなら行けるでしょう。


増やす理由がわからない。辞書を追加するだけでもよい。

 
タグコノウ

配列のサイズが大きすぎるため。

1.単語の最大文字数は100文字までと決めています。これは明らかにやりすぎです。30に減らすことができた。

2.また、可能な文字数も過大であることが判明しました。できるだけいろいろなキャラクターのスペースを取ることにしました。削減できる。

3.衝突」、つまり最初の文字と単語の文字数で単語をマッチングさせる回数は100回に設定されています。これもやりすぎです。50に減らすことができます。


サイズを大きくする理由はないと思います。別の辞書を作るだけかもしれません。

問題は、辞書のことではありません。辞書はあくまでアルゴリズムの構築の一例です。この例のように100個ではなく、1e10個以上あるかもしれません...。このような場合のアレイの大きさは?

例えば、利用可能なすべてのティック履歴を配列に集めます。1ミリ秒に1回以上の刻みがある可能性があるので、配列は1次元にできない...。1ミリ秒の間に最大で何回ティックがあったのか?2か5か?この場合、配列の次元は どうすればいいのでしょうか?どれだけのメモリが無駄になるのでしょうか?

 
Alexey Viktorov:

例えば、利用可能なすべてのティック履歴を配列に集めます。

ここまで書いて、ふと思ったのですが、スレッドで議論されているような方法でティックを保存するのは現実的な作業ではありませんね。これらは時間順にソートされ、単純な配列に格納される。

History Order/Dealsでも同じです。そして、HistorySelectから 判断して、時間ごとに配列に格納されている。また、チケットやIDでレコードを検索するようなことは(現在の実装では)できないと思うのですが。

そしてすべて、名前のある歴史の場合、このようなものを作るのは合理的でないからです。練習用の簡単な配列で十分です。

だからこそ、トレーディングの現場における実践的なタスクの表現に興味があるのです。


HistorySelectの高速化を図る場合、ハッシュやディクショナリーではなく、キャッシュで解決しているのではないでしょうか。

 
fxsaber

ここまで書いて、ふと思ったのですが、スレッドで議論されているような方法でティックを保存するのは現実的な作業ではありませんね。これらは時間順にソートされ、単純な配列に格納される。

History Order/Dealsの場合も同様です。そして、HistorySelectから判断して、時間ごとに配列に格納されている。また、チケットやIDでレコードを検索するようなことは(現在の実装では)できないと思うのですが。

そしてすべて、名前のある歴史の場合、このようなものを作るのは合理的でないからです。練習用の簡単な配列で十分です。

だからこそ、トレーディングの現場における実践的なタスクの表現 に興味があるのです。


HistorySelectを高速化する場合、ハッシュ辞書ではなく、キャッシュで解決しているのではないでしょうか。

反論はありませんが、もし誰かが何かのタスクをそのように実装したいのであれば、その場でフラグを立ててください...。

意味がないと思っている人がいる、使いこなせない人がいる...。そして、どちらの場合も、よりシンプルな実装があります。しかし、トレーディングが「明日」どのように発展するかは誰にもわからない...。それがない状態で必要になるよりは、あってもないままの方がいいのかもしれません。

 
アレクセイ・ヴィクトロフ

問題は、辞書のことではありません。辞書はアルゴリズム構築の一例に過ぎない。そして、この例のように100個ではなく、1e10個以上あるかもしれない...。このような場合のアレイの大きさは?

例えば、利用可能なすべてのティック履歴を配列に集めます。1ミリ秒に1回以上の刻みがある可能性があるので、配列は1次元にできない...。しかし、1ミリ秒の間に最大で何回のティックがあったのだろうか?2か5か?この場合、配列の次元は どうすればいいのでしょうか?どれだけのメモリが無駄になるのか?

便利な辞書を構築するという課題を解決していたのです。

チックやその他の要素にはそれぞれ固有の性質があり、それをうまくインデックス化することで、保存場所に素早くアクセスできるようになります。

データへの高速アクセスという課題の本質は、ある要素の分類可能ないくつかの特性を識別し、それらにインデックスを付けることである。

要素を取り出し、そこからインデックスを取得できる便利なプロパティを見つけ、インデックスを通じて格納場所へのアクセスを得る。

インデックスが十分でない場合(例えば、最初の文字と文字数のインデックスはできるが、他のプロパティは便利なインデックスを提供しない)、その周囲の領域内の要素に対して直接ブルートフォースを行っています。

原理は普遍的なもので、実装はさまざまです。