일반 클래스 라이브러리 - 버그, 설명, 질문, 사용 기능 및 제안 사항 - 페이지 23

 
//+------------------------------------------------------------------+
//|                                              CompareFunction.mqh |
//|                   Copyright 2016-2017, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Generic\Interfaces\IComparable.mqh>
//+------------------------------------------------------------------+
//| Compares two objects and returns a value indicating whether one  |
//| is less than, equal to, or greater than the other.               |
//+------------------------------------------------------------------+
int Compare( const bool x, const bool y)
  {
   if (x>y)
       return ( 1 );
   else if (x<y)
       return (- 1 );
   else
       return ( 0 );
  }


함수는 전역 수준에서 선언됩니다. 이러한 이유로 비교 사용자와 충돌이 있습니다.

'Compare' - function already defined and has body

명명 충돌을 줄이기 위해 작성자가 모든 전역 일반 도우미 함수를 공개 정적 메서드로 만들 수 있습니까?

 

fxsaber :

명명 충돌을 줄이기 위해 작성자가 모든 전역 일반 도우미 함수를 공개 정적 메서드로 만들 수 있습니까?

거래, 자동 거래 시스템 및 거래 전략 테스트에 관한 포럼

컴파일러 버그: 'operator=' - 구조에 개체가 있고 복사할 수 없습니다.

fxsaber 2018.09.10 11:00 2018.09.10 10:00:13 KO
알렉세이 나보이코프 :
이것은 당분간입니다. 모든 것이 한데 뭉쳐지면 붕괴가 불가피하다.) 누군가의 라이브러리를 포함하고 싶다면 작성자는 동일한 클래스 및 함수 이름을 사용하여 동일한 "원시적" 방식으로 글을 쓰는 것으로 밝혀졌다.

매크로로 이기겠다 매크로로 이기겠다

그러나 매크로는 어떻습니까?
 
A100 :
그러나 매크로는 어떻습니까?

그는 자신에 대해 이야기하지 않았습니다.

 

토론의 모든 페이지를 읽었지만 사용법을 이해하지 못하셨습니까?

누구나 예제를 제공할 수 있습니까?

 
Vladimir Pastushak :

토론의 모든 페이지를 읽었지만 사용법을 이해하지 못하셨습니까?

누구나 예제를 제공할 수 있습니까?

죽여. 지금의 형태로는 사용할 수 없습니다. 대신 표준 CObject + CDictionary 를 사용하십시오. 대부분의 작업에서는 이것으로 충분합니다.

 
Vasiliy Sokolov :


수업 설명
캐시맵 키-값 집합입니다. 키로 요소를 효율적으로 삽입, 검색 및 검색할 수 있습니다. 키는 고유해야 합니다. 예를 들어, CHashMap은 지정된 번호로 주문을 즉시 찾을 수 있으며, 여기서 번호는 키로 사용됩니다.

키로 값을 얻는 것에 대한 질문입니다. 라이브러리 코드에서 이 메서드는 다음과 같습니다.

 //+------------------------------------------------------------------+
//| Find index of entry with specified key.                          |
//+------------------------------------------------------------------+
template < typename TKey, typename TValue>
int CHashMap::FindEntry(TKey key)
  {
   if (m_capacity!= NULL )
     {
       //--- get hash code from key
       int hash_code=m_comparer.HashCode(key)& 0x7FFFFFFF ;
       //--- search pair with specified key
       for ( int i=m_buckets[hash_code%m_capacity]; i>= 0 ; i=m_entries[i].next)
         if (m_entries[i].hash_code==hash_code && m_comparer.Equals(m_entries[i].key,key))
             return (i);
     }
   return (- 1 );
  }

소스의 ME 탐색 도구(ALT+G 및 CTRL+-)는 이 라이브러리에서 작동하지 않습니다. 따라서 논리를 따르기가 매우 어렵습니다. 특히 선택한 주기에서 아직 초기값을 찾지 못했습니다. 그러나 속도가 있으면이 값이 키 수보다 훨씬 작아야한다는 이해가 있습니다.


이 기능에서 속도를 얻을 수 있었던 이유를 설명해 주십시오. 오버플로가 분명히 존재합니다. 하지만 어떤 이유에서인지 짧은 것 같습니다.


위협 디버거와 함께 단계별로 걸었습니다. TKey = int: m_bucket[Array[i]] = i의 예에서 모든 것이 명확해졌습니다. Array[i] == Array[j](i != j)인 경우 충돌만 처리하지 않습니다.

 
fxsaber :

키로 값을 얻는 것에 대한 질문입니다. 라이브러리 코드에서 이 메서드는 다음과 같습니다.
이 기능에서 속도를 얻을 수 있었던 이유를 설명해 주십시오. 오버플로가 분명히 존재합니다. 하지만 어떤 이유에서인지 짧은 것 같습니다.

한 번에 CHashMap 의 작동 원리를 분석하고 설명했습니다.
이 스레드에서 가장 가능성이 높은 레코드를 찾아야 합니다.

 

거래, 자동 거래 시스템 및 거래 전략 테스트에 관한 포럼

일반 클래스 라이브러리 - 버그, 설명, 질문, 사용법 및 제안

Sergey Dzyublik , 2017.12.11 13:41

CHashMap의 현재 구현에 대해 간략하게:

template<typename TKey,typename TValue>
class CHashMap: public IMap<TKey,TValue>
  {
protected :
   int                m_buckets[];                        
   Entry<TKey,TValue>m_entries[];
   int                m_count;
   int                m_free_list;
   int                m_free_count;
   IEqualityComparer<TKey>*m_comparer;
   bool               m_delete_comparer;

     .................................

.................................

}

먼저 Entry<TKey,TValue> 가 무엇인지 이해해야 합니다.
사실, 이것은 다음을 포함하는 CLinkedList와 같은 노드입니다.

- 키 및 값 컨테이너에 배치
- 키에 대한 캐시된 해시 값 - hash_code
- next - 단일 연결 목록을 통해 충돌을 해결하기 위해 다음 Entry<TKey,TValue> 에 대한 "포인터"


m_entries[] - 추가된 키와 값인 hash_code 다음이 배치되는 "셀"의 배열입니다. 어레이의 크기는 용량에 해당합니다.
m_count - m_entries에서 사용되지 않은 첫 번째 셀의 인덱스를 나타냅니다. 초기 값은 0이고 용량까지 증가하고 모든 어레이는 모든 어레이의 용량 및 크기가 증가하여 재구축됩니다.
m_buckets[] - m_entries[]의 인덱스 배열. 기본값은 -1입니다. 어레이의 크기는 용량에 해당합니다.


충돌 없음, CHashMap 컨테이너에 고유 값 추가:

  1. 키로 해시를 계산하면 hash_code를 얻습니다.
  2. 인덱스 m_count의 m_entries[]에 key, value, hash_code 값을 배치합니다. (예제에 충돌이 없기 때문에 다음 = -1)
  3. index hash_code % (ArraySize(m_buckets))에 m_buckets[]를 m_entries[]에 새로 추가된 요소의 인덱스 값(m_count)에 넣습니다.
  4. m_count의 값을 +1 증가시킵니다.

충돌 없음, CHashMap 컨테이너에서 키로 값 가져오기:

  1. 키로 해시를 계산하면 hash_code를 얻습니다.
  2. m_buckets[]에서 index hash_code %(ArraySize(m_buckets))로 배열 m_entries[]에서 인덱스인 값을 얻습니다.
  3. 얻은 인덱스 m_buckets[hash_code % (ArraySize(m_buckets))]에 의해 배열 m_entries[]에서 값 값을 얻습니다.

충돌 해결:

다른 키의 경우 hash_code_key_1 %(ArraySize(m_buckets))는 hash_code_key_2 %(ArraySize(m_buckets))와 같습니다. 이것을 충돌이라고 합니다.
충돌로 m_entries[]에 추가된 모든 요소는 다음을 통해 단일 연결 목록으로 서로 연결됩니다( Entry<TKey,TValue> 구조 참조).
그리고 m_buckets[]는 항상 이 충돌 목록에서 첫 번째 헤드 요소의 인덱스를 가리킵니다.
충돌이 있는 하나의 큰 목록이 아니라 많은 작은 목록이 나타납니다.


충돌, CHashMap 컨테이너에서 키로 값 가져오기:

  1. 키로 해시를 계산하면 hash_code를 얻습니다.
  2. m_buckets[]에서 index hash_code %(ArraySize(m_buckets))로 배열 m_entries[]에서 인덱스인 값을 얻습니다.
  3. 다음 값이 충돌이 있음을 나타내는 -1과 같지 않음을 알 수 있습니다.
  4. m_entries[] 요소의 단일 연결 목록을 살펴보고 원하는 값을 저장된 키와 동일한지 비교합니다.


CHashMap 컨테이너에서 값 제거:

- m_entries[]에서 셀을 삭제할 때 삭제가 발생하지 않는 셀은 free로 지정되고 hash_code = -1입니다.
- 자유 셀은 고유한 자유 셀 목록을 형성합니다(Entry<TKey,TValue>의 동일한 다음을 통해). m_free_list 는 목록 헤드 인덱스를 담당합니다.
- 컨테이너에 새 값이 추가되면 빈 셀이 먼저 사용됩니다.
- m_free_count 는 현재 사용 가능한 셀 수를 제어하는 데 사용됩니다.


해시 테이블 재구축(용량 증가 프로세스):

- 재구축은 용량이 100% 찼을 때만 발생합니다.
- 목록에서 다음 용량을 가져옵니다.

 const static int   CPrimeGenerator::s_primes[]=
  {
   3 , 7 , 11 , 17 , 23 , 29 , 37 , 47 , 59 , 71 , 89 , 107 , 131 , 163 , 197 , 239 , 293 , 353 , 431 , 521 , 631 , 761 , 919 ,
   1103 , 1327 , 1597 , 1931 , 2333 , 2801 , 3371 , 4049 , 4861 , 5839 , 7013 , 8419 , 10103 , 12143 , 14591 ,
   17519 , 21023 , 25229 , 30293 , 36353 , 43627 , 52361 , 62851 , 75431 , 90523 , 108631 , 130363 , 156437 ,
   187751 , 225307 , 270371 , 324449 , 389357 , 467237 , 560689 , 672827 , 807403 , 968897 , 1162687 , 1395263 ,
   1674319 , 2009191 , 2411033 , 2893249 , 3471899 , 4166287 , 4999559 , 5999471 , 7199369
  };

- m_entries[] 및 m_buckets[] 배열의 크기가 증가합니다.
- m_buckets[]가 지워지고 m_entries[]의 데이터를 기반으로 완전히 다시 채워집니다(키에 대한 캐시된 해시 값 - hash_code).


2017.12.11 기준 동작 설명
현재 일부 세부 사항/계수가 추가/변경될 수 있습니다.

 
Sergey Dzyublik :

한 번에 CHashMap 의 작동 원리를 분석하고 설명했습니다.
이 스레드에서 가장 가능성이 높은 레코드를 찾아야 합니다.

설립하다

거래, 자동 거래 시스템 및 거래 전략 테스트에 관한 포럼

일반 클래스 라이브러리 - 버그, 설명, 질문, 사용법 및 제안

Sergey Dzyublik , 2017.12.07 14:21


이 예에서 해시는 학생의 생일입니다.
365개의 선반이 있는 벽장에는 학생의 일기가 들어 있습니다.
우리는 학생의 생일에 해당하는 선반에 각 일기를 넣습니다.

우리는 Petrov의 학생의 일기가 필요하고 그가 언제 태어났는지 압니다.
이제 생일을 기준으로 O(1)에서 다른 학생의 일기와 마찬가지로 Petrov의 일기를 쉽게 찾을 수 있습니다.
두 학생의 생일이 같은 경우는 예외입니다. 이를 충돌이라고 합니다.

충돌 해결은 두 개 이상의 일기 중 어느 것이 필요한지 결정하기 위해 추가 정보를 사용하는 것입니다.
목록을 통해 해결하는 것은 충돌에 참여하는 모든 요소를 원하는 요소와 일치시키기 위해 단순하게 순차적으로 열거하는 것입니다. 각 일기를 찢고 그것이 누구인지 확인하십시오.
Subhash 정렬은 충돌과 관련된 요소의 해시 테이블을 구성하지만 다른 기준에 따릅니다. 예를 들어, 학생이 태어났을 때.


이 주제에 관심이 있다면 알고리즘 및 데이터 구조 에 대한 YouTube의 MailRu 과정을 추천합니다.

거래, 자동 거래 시스템 및 거래 전략 테스트에 관한 포럼

일반 클래스 라이브러리 - 버그, 설명, 질문, 사용법 및 제안

Sergey Dzyublik , 2017.12.08 14:40

게으른 사람을 위한 주제에 대한 기본 사항:
https://www.slideshare.net/mkurnosov/6-32402313

실제로는 모든 것이 훨씬 더 복잡하며 관련 문헌이나 좋은 "알고리즘 및 데이터 구조" 과정에서 논의됩니다.


감사합니다. 디버그가 도움이 되었습니다. 충돌에 대한 작은 목록이 있습니다. 나는 가지를 따라 달려갔고 겁에 질렸다. 그가 있었던 것으로 밝혀졌습니다 ...

 
Sergey Dzyublik :
2017.12.11 기준 동작 설명

현재 일부 세부 사항/계수가 추가/변경될 수 있습니다.

정말 감사합니다! 그들은 내 설명에 많은 도움을 받았습니다.