Standart özelliklerin/yaklaşımların alternatif uygulamaları - sayfa 3

 
fxsaber :
#import ex5'in optimizasyonun kötülüğü olduğu ortaya çıktı.

Küresel optimizasyon olasılığı açısından - evet.

Kodu küçültmeye çalışmadan oldukça agresif satır içi işlemimiz var. Bu nedenle global optimizasyon modunda çok iyi kod üretiyoruz.

Bu, ortaya çıkan hızı ön plana koyduğumuz derleme zamanında görülebilir.

 
prostotrader :

fxsaber

kodunuzda bir hata var

Teşekkürler, düzelttim.
 double MyNormalizeDouble( const double Value, const uint digits )
{
   static const double Points[] = { 1.0 e- 0 , 1.0 e- 1 , 1.0 e- 2 , 1.0 e- 3 , 1.0 e- 4 , 1.0 e- 5 , 1.0 e- 6 , 1.0 e- 7 , 1.0 e- 8 };
   const double point = digits > 8 ? 1.0 e- 8 : Points[digits];

   return (( long )((Value > 0 ) ? Value / point + HALF_PLUS : Value / point - HALF_PLUS) * point);
}
 
fxsaber :
Teşekkürler, düzelttim.

Hala bir hata

sonunda 5 olmalı

 
prostotrader :

Hala bir hata

Bu bir hata değil, yuvarlamadır. Standart versiyonun yaptığı tam olarak budur.
 
fxsaber :
Bu bir hata değil, yuvarlamadır. Standart versiyonun yaptığı tam olarak budur.
Bir hata yaptım, yanlış ekranı gönderdim, tekrar bakın (resmi değiştiriyorum)
 

İşte size kod, test edin

 //+------------------------------------------------------------------+
//|                                                         Test.mq5 |
//|                        Copyright 2016, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, MetaQuotes Software Corp."
#property link        "https://www.mql5.com"
#property version    "1.00"
#define EPSILON ( 1.0 e- 7 + 1.0 e- 13 )
#define HALF_PLUS  ( 0.5 + EPSILON)
#property indicator_separate_window
#property indicator_plots    1
#property indicator_buffers 1
double d_value = 12345.012345 ;
//
double MyNormalizeDouble( const double Value, const uint digits )
{
   static const double Points[] = { 1.0 e- 0 , 1.0 e- 1 , 1.0 e- 2 , 1.0 e- 3 , 1.0 e- 4 , 1.0 e- 5 , 1.0 e- 6 , 1.0 e- 7 , 1.0 e- 8 };
   const double point = digits > 8 ? 1.0 e- 8 : Points[digits];

   return (( long )((Value > 0 ) ? Value / point + HALF_PLUS : Value / point - HALF_PLUS) * point);
}
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit ()
  {
//--- indicator buffers mapping
   double new_value = MyNormalizeDouble(d_value, 0 );
   new_value = NormalizeDouble (d_value, 0 );
   new_value = MyNormalizeDouble(d_value, 1 );
   new_value = NormalizeDouble (d_value, 1 );
   new_value = MyNormalizeDouble(d_value, 2 );
   new_value = NormalizeDouble (d_value, 2 );
   new_value = MyNormalizeDouble(d_value, 3 );
   new_value = NormalizeDouble (d_value, 3 );
   new_value = MyNormalizeDouble(d_value, 4 );
   new_value = NormalizeDouble (d_value, 4 );
   new_value = MyNormalizeDouble(d_value, 5 );
   new_value = NormalizeDouble (d_value, 5 );
   new_value = MyNormalizeDouble(d_value, 6 );
   new_value = NormalizeDouble (d_value, 6 );
   new_value = MyNormalizeDouble(d_value, 7 );
   new_value = NormalizeDouble (d_value, 7 );
   new_value = MyNormalizeDouble(d_value, 8 );
   new_value = NormalizeDouble (d_value, 8 );
   new_value = MyNormalizeDouble(d_value, 9 );
   new_value = NormalizeDouble (d_value, 9 );
   if (new_value == 0.0 )
   {}  
//---
   return ( INIT_SUCCEEDED );
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate ( const int rates_total,
                 const int prev_calculated,
                 const int begin,
                 const double &price[])
  {
//---
   
//--- return value of prev_calculated for next call
   return (rates_total);
  }
//+------------------------------------------------------------------+
 
prostotrader :

İşte size kod, test edin

 void OnStart ( void )
{
   double Val = 12345.012345 ;
  
   double Val2 = Val / 1.0 e- 5 ;
  Val2 += HALF_PLUS; // Val2 == 1234501235.0
  
   long Val3 = ( long )Val2; // Val3 == 1234501234
    
   return ;
};

Val2 doğru. Val3'ü uzun süre kullandıktan sonra doğru değil. Görünüşe göre, kayan noktalı sayıların çift temsilinin bazı özellikleri. EPSİLON'u artırmak gereklidir. Uykulu bir kafa düşünemiyorum. Belki bilen biri müdahale edebilir.

Geliştiricilerin bunu hangi nedenlerle yazdığını anlamak gerekli olacaktır.

 //+------------------------------------------------------------------+
//| Сравнивает два значения типа double.                             |
//| RESULT                                                           |
//|   Возвращает истину, если значения равны и                       |
//|   ложь в противном случе.                                        |
//+------------------------------------------------------------------+
bool CEnvironment::DoubleEquals( const double a, const double b)
  {
//---
   return ( fabs (a-b)<= 16 * DBL_EPSILON * fmax ( fabs (a), fabs (b)));
//---
  }

Görünüşe göre köpek buraya gömülmüş.

 
Artık her zaman doğru çalışıyor, ancak orijinalinden yalnızca %10 daha hızlı
 double MyNormalizeDouble( const double Value, const uint digits )
{
   static const double Points[] = { 1.0 e- 0 , 1.0 e- 1 , 1.0 e- 2 , 1.0 e- 3 , 1.0 e- 4 , 1.0 e- 5 , 1.0 e- 6 , 1.0 e- 7 , 1.0 e- 8 };
   const double point = digits > 8 ? 1.0 e- 8 : Points[digits];
   const long Integer = ( long )Value; // чтобы не создавать крайне медленный относительный epsilon

   return (( long )((Value > 0 ) ? (Value - Integer) / point + HALF_PLUS : (Value - Integer) / point - HALF_PLUS) * point + Integer);
}
prostotrader , Tutarsızlıkları bulduğunuz için teşekkürler!
 
fxsaber :

Görünüşe göre köpek buraya gömülmüş.

Bacaklar RSDN forumundan büyüyor

DBL_EPSILON, uygulamada 1.0 sayısına 1 (bir!) anlamlı üs biti farkı tanımlar. Pratikte böyle bir fark oluşmaz - sayılar ya kesinlikle eşittir ya da birden fazla anlamlı bit ile farklılık gösterebilir. Bu nedenle, en az anlamlı 4 bitteki (veya mevcut yaklaşık 16'dan yaklaşık bir buçuk son önemli ondalık basamaktaki) farkı yok saymak için 16*DBL_EPSILON gibi bir şey almanız gerekir.

Elbette, sayı aralığının az çok bilindiği ve tahmin edilebilir olduğu durumlar vardır. 0...1000 diyelim. Bu durumda yaklaşık eşitlik için karşılaştırma yapmak için 1000*16*DBL_EPSILON gibi bir sabit alabilirsiniz. Ancak böyle bir karşılaştırmanın aslında tüm kayan nokta fikrini sabit bir noktaya dönüştürdüğünü unutmayın (tahmin edin neden).  

 

Bazen orijinalinden birkaç büyüklük sırası daha hızlı olan CopyTicks varyantı (> 0'dan)

 int MyCopyTicks( const string Symb, MqlTick & Ticks[], const uint flags = COPY_TICKS_ALL , const ulong from = 0 , const uint count = 0 )
{
   int Res = (from == 0 ) ? CopyTicks (Symb, Ticks, flags, 0 , count) : - 1 ;
  
   if (from > 0 )
  {    
     uint count2 = 1 ;
    
     MqlTick NewTicks[];    
     int Amount = CopyTicks (Symb, NewTicks, flags, 0 , count2);
    
     while ((Amount > 0 ) && (( ulong )NewTicks[ 0 ].time_msc >= from))
    {
      count2 <<= 1 ;
      
      Amount = CopyTicks (Symb, NewTicks, flags, 0 , count2);
    }

     for ( int i = 1; i < Amount; i++)
       if (( ulong )NewTicks[i].time_msc >= from)
      {
        Res = ArrayCopy (Ticks, NewTicks, 0 , i, (count == 0 ) ? 2000 : count);
        
         break ;
      }    
  }
  
   return (Res);
}