Löschen eines Arrays mit definierten Element(en) - Seite 15

 
Sergey Dzyublik:

Es gab bereits eine Diskussion über den []-Operator, dass er für diese C++-Sprache zu langsam ist. Ich hätte nicht gedacht, dass es so langsam ist, dass ArrayCopy es zerreißen kann.

Das ist eine separate Frage zu Inkrementen innerhalb von Operatoren.

 
Stanislav Dray:

Warum hast du dich selbst repariert und mich rausgeschmissen? Nicht gut.

Ich habe niemanden rausgeworfen. Was , habe ich zurückgegeben )))

 
Konstantin Nikitin:

Sie haben niemanden rausgeschmissen. Was , haben Sie zurückgegeben ))))

Sie haben also die 11. heruntergeladen, meine ist die 12. (unten) und Sie haben die 11. korrigiert und als 13. zurückgegeben.

 
TheXpert:

Es gab bereits eine Diskussion über den []-Operator, dass er für diese C++-Sprache zu langsam ist. Ich hätte nicht gedacht, dass es so langsam ist, dass ArrayCopy es zerreißen kann.

Das ist eine separate Frage zu Inkrementen innerhalb von Operatoren.

Es gibt nicht einmal einen Grund, hier unnötige Operationen durchzuführen. Wenn eine Schleife läuft. Es ist nicht nötig zu prüfen, ob das aktuelle Element beim Kopieren außerhalb der Grenzen liegt. Sie wird innerhalb der Grenzen liegen. Und es macht keinen Sinn, etwas hinzuzufügen oder eine weitere Variable zu ziehen. Wenn es standardmäßig ein i.
Jedenfalls gibt es allerlei triviales Zeug. Nur zur Information

 
Stanislav Dray:

Sie haben also die 11. heruntergeladen, meine ist die 12. (unten) und Sie haben die 11. korrigiert und als 13. zurückgegeben.

Ich habe nicht darauf geachtet. Ersetzte die Datei.

 

auch in diesem gnadenlosen Wettbewerb skizziert :-)

template <typename T>
int copyFilter1(const T &src[],T &dst[],T x)
{
        int i=0,j=0,k;
        int total=ArraySize(src);
        ArrayResize(dst,total);
        for(;;) {
                // считаем сколько копировать
                for(k=0;k<total && src[i]!=x;)
                        k++;
                // копируем
                if (k) {        
                        ArrayCopy(dst,src,j,i,k);
                        i+=k;
                        j+=k;
                        total-=k;
                }
                // пропускаем
                for(k=0;k<total && src[i]==x;) 
                        k++;
                if (k) {
                        i+=k;
                        total-=k;
                } else break;
        }
        ArrayResize(dst,j);
        return j;
}

template <typename T>
int copyFilter2(const T &src[],T &dst[],T x)
{
        int i=0,j=0,k;
        int total=ArraySize(src);
        ArrayResize(dst,total);
        for(;i<total;) {
                // копируем всё что не равно x
                for(;i<total && src[i]!=x;i++,j++)
                        dst[j]=src[i];
                // пропускаем всё что равно x
                for(;i<total && src[i]==x;)
                        i++;
        }
        ArrayResize(dst,j);
        return j;
}

Nochmals, nicht überprüft :-) sollte funktionieren...

 
Stanislav Dray:

Sie haben Tests empfohlen, die Fehler enthalten (Semko und Pavlov).

Danke, ich habe es korrigiert.

Maxim Kuznetsov:

auch in diesem gnadenlosen Wettbewerb skizziert :-)

Nochmals, nicht überprüft :-) sollte funktionieren...

enthalten, aber mit der ersten Variante ist etwas nicht in Ordnung

2018.11.15 06:19:01.929 ArrayDeleteValue__13 (.BrentCrud,M1)    вариант Pastushak   : Контрольная сумма = 7225.756203; элементов - 998992; время выполнения - 141053 микросекунд
2018.11.15 06:19:01.934 ArrayDeleteValue__13 (.BrentCrud,M1)    вариант Korotky     : Контрольная сумма = 7225.756203; элементов - 998992; время выполнения -   2494 микросекунд
2018.11.15 06:19:01.938 ArrayDeleteValue__13 (.BrentCrud,M1)    вариант Fedoseev    : Контрольная сумма = 7225.756203; элементов - 998992; время выполнения -   1869 микросекунд
2018.11.15 06:19:01.941 ArrayDeleteValue__13 (.BrentCrud,M1)    вариант Semko       : Контрольная сумма = 7225.756203; элементов - 998992; время выполнения -    785 микросекунд
2018.11.15 06:19:01.945 ArrayDeleteValue__13 (.BrentCrud,M1)    вариант Nikitin     : Контрольная сумма = 7225.756203; элементов - 998992; время выполнения -   2039 микросекунд
2018.11.15 06:19:01.952 ArrayDeleteValue__13 (.BrentCrud,M1)    вариант Vladimir    : Контрольная сумма = 7225.756203; элементов - 998992; время выполнения -   4385 микросекунд
2018.11.15 06:19:01.961 ArrayDeleteValue__13 (.BrentCrud,M1)    вариант Peter       : Контрольная сумма = 7225.756203; элементов - 998992; время выполнения -   7476 микросекунд
2018.11.15 06:19:01.965 ArrayDeleteValue__13 (.BrentCrud,M1)    вариант fann95      : Контрольная сумма = 7225.756203; элементов - 998992; время выполнения -   1255 микросекунд
2018.11.15 06:19:01.969 ArrayDeleteValue__13 (.BrentCrud,M1)    вариант Kuznetsov1  : Контрольная сумма = 7219.502578; элементов - 1000000; время выполнения -   2016 микросекунд
2018.11.15 06:19:01.975 ArrayDeleteValue__13 (.BrentCrud,M1)    вариант Kuznetsov2  : Контрольная сумма = 7225.756203; элементов - 998992; время выполнения -   3965 микросекунд
2018.11.15 06:19:01.975 ArrayDeleteValue__13 (.BrentCrud,M1)    
2018.11.15 06:19:01.975 ArrayDeleteValue__13 (.BrentCrud,M1)    === Порядок в массиве не сохраняется ===
2018.11.15 06:19:01.978 ArrayDeleteValue__13 (.BrentCrud,M1)    вариант Kuznetsov3  : Контрольная сумма = 7222.657252; элементов - 998992; время выполнения -    694 микросекунд
Dateien:
 

Ich komme zurück zu meinem missverstandenen Unterschied in der Ausführungszeit von fast 100% identisch in Logik und Anzahl der Prüfungen und Summen von zwei Schleifen:

Also noch einmal, warum eine solche Variante von Kuznetsovs Code:

    for(;;)
     {
      while(arr[i]!=x && i<j) i++;
      while(arr[j]==x && i<j) j--;
      if(i<j)
        {
         arr[i++]=arr[j--];
        }
      else break;
     }

funktioniert mehr als doppelt so schnell wie diejenige, die genau das Gleiche tut:

   while(i<j)
     {
      if(arr[i]==x)
         if(arr[j]!=x) arr[i++]=arr[j--];
      else j--;
      else i++;
     }

Was sind die Wunder des Compilers?
Ist ein solches Design wirklich möglich?

while(arr[i]!=x && i<j) i++;

der Compiler einen speziellen Suchbefehl des Assemblers für den Prozessor findet? Aber es gibt eine zusätzliche Prüfung i<j im Inneren, nicht wahr?

Denn die gleiche Sache durch für wird viel langsamer ausgeführt:

for (;;) if (arr[i]!=x && i<j) i++; else break;

Ich füge den Code des Demonstrationsskripts bei

2018.11.15 13:30:51.354 TestLoop (EURUSD,D1)    вариант while:    Контрольная сумма = 7697.499145747599; элементов - 998975; время выполнения = 771 микросекунд
2018.11.15 13:30:51.357 TestLoop (EURUSD,D1)    вариант for:      Контрольная сумма = 7697.499145747599; элементов - 998975; время выполнения = 1051 микросекунд
2018.11.15 13:30:51.360 TestLoop (EURUSD,D1)    вариант slow:     Контрольная сумма = 7697.499145747599; элементов - 998975; время выполнения = 1531 микросекунд

Das ist oft der Fall. Sie beschäftigen sich mit irgendwelchem unnötigen Kram und finden etwas sehr Interessantes heraus.

Entwickler, könnten Sie einen Blick auf den ausführbaren Code werfen und sehen, was den Unterschied ausmacht?

Sie müssen die Logik des Compilers verstehen, um in Zukunft optimalere Algorithmen erstellen zu können.

Dateien:
TestLoop.mq5  10 kb
 
Nikolai Semko

Interessante Beobachtung. und für das Interesse, lief der Code

void OnStart()
{
     int array[], arr[];
     ArrayResize(arr,1000000);
     for(int i=0; i<1000000;i++)
          arr[i] = rand()%1000;

     int i=0;
     ulong t=GetMicrosecondCount();
     for(; i<1000000; i++)
          int j = arr[i];
     t = GetMicrosecondCount()-t;
     Print("FOR: ", t);
     
     t=GetMicrosecondCount();
     i=0;
     for(;;)
     {
          if( i>=1000000 )
               break;
          int j = arr[i];
          i++;
     }
     t = GetMicrosecondCount()-t;
     Print("FOR-1: ", t);
     
     t=GetMicrosecondCount();
     i=0;
     while(i<1000000)
     {
          int j = arr[i];
          i++;
     }
     t = GetMicrosecondCount()-t;
     Print("WHILE: ", t);
     
     t=GetMicrosecondCount();
     i=0;
     while(true)
     {
          if( i>=1000000 )
               break;
          int j = arr[i];
          i++;
     }
     t = GetMicrosecondCount()-t;
     Print("WHILE-1: ", t);
}


 
Nikolai Semko:

Ich komme zurück zu meinem missverstandenen Unterschied in der Ausführungszeit von fast 100% identisch in Logik und Anzahl der Prüfungen und Summen von zwei Schleifen:

Also noch einmal, warum eine solche Variante von Kuznetsovs Code:

arbeitet mehr als doppelt so schnell wie eine, die genau dasselbe tut:

Was sind die Wunder des Compilers?
Ist es wirklich möglich, dass ein solches Konstrukt:

der Compiler einen speziellen Suchbefehl des Assemblers für den Prozessor findet? Aber es gibt eine zusätzliche Prüfung i<j im Inneren, nicht wahr?

Denn die gleiche Sache durch für wird viel langsamer ausgeführt:

Ich füge den Code des Demonstrationsskripts bei

Das ist oft der Fall. Sie beschäftigen sich mit irgendwelchem unnötigen Kram und finden etwas sehr Interessantes heraus.

Entwickler, könnten Sie einen Blick auf den ausführbaren Code werfen und sehen, was den Unterschied ausmacht?

Sie müssen die Logik des Compilers verstehen, um in Zukunft optimalere Algorithmen erstellen zu können.

Ich denke, die Flaggen passen gut zueinander:
http://osinavi.ru/asm/4.php

Und für unnötige Operatoren/Vergleiche...