MQL4 ustaları için soru. Yine Çift Karşılaştırma hakkında. - sayfa 6

 
VBAG :
...
Irtron'un önerdiği kodun güzelliği, kompaktlığıdır (kesinlikle başka bir şey değil - değişkenlerden tasarruf bile!)
...


Burada Irtron'un önerdiği yönteme baktım.

int ComparePrice(double a, double b, double digit)
{
     a -= b;
     b = digit;
     if (a > b)
         return (1);
     if (a < -b)
         return (-1);
     return (0);
 }

Hem Kompakt hem de benimkinden daha hızlı, ancak ilk bakışta bile şüpheli görünüyor, çünkü karşılaştırmada iki çift değişken söz konusu !!!!

Bu şemada, yalnızca basamak bir sabit gibi davranır ve karşılaştırılabilir ve normalleştirilmemiş bir double olduğu için aynı zamanda karşılaştırılan a değişkeni de öyle kaldı!
Bu şüphe uyandırır mı? (Sabit derken normal sabitleri - "#define" ve işlemlere katılmayan değişkenleri kastediyorum).

Ayrıca, diğer başlıklarda, geliştiricilerin kendileri, çift sabitleri bile karşılaştırmamanın daha iyi olduğunu yazdı !!!
Ayrıca NormalizeDouble (a) !OC! yapmak da doğru değil! NormalizeÇift(b), !OC! - karşılaştırma operatörü!

Üstelik orijinal versiyonda, sabit rakamlar yerine şu şekildeydi b = Nokta / 2 - zaten iki normalleştirilmemiş değişkenden ikisi var mı?

Bu seçeneğin dahiyane olduğuna inanmak istiyorum ama önce şüphelerimi giderin!

Belki birisi benim versiyonumda hatalar bulur?
 
gravity001 :

Burada Irtron'un önerdiği yönteme baktım.

int ComparePrice(double a, double b, double digit)
{
     a -= b;
     b = digit;
     if (a > b)
         return (1);
     if (a < -b)
         return (-1);
     return (0);
 }
Ben farklı bir yöntem önerdim.
Dikkatli bakın lütfen.


Üstelik orijinal versiyonda, sabit rakamlar yerine şu şekildeydi b = Nokta / 2 - zaten iki normalleştirilmemiş değişkenden ikisi var mı?

Hangi seçeneklerden bahsediyoruz?

Normalleşmeden bahsetmiştim. Önce, neden kullanacağımızı ve ancak o zaman nasıl ve nerede kullanacağımızı söyleyin.

Örneğin, yukarıdaki tartışmada bir tür başarı olarak bahsedilen fiyatları neden tam olarak 14 ondalık basamakla karşılaştırdığınızı biliyor olabilirsiniz? :) Size önerdiğim fonksiyonun ComparePrice olduğunu hatırlatmama izin verin. :)
 

Irtron писал (а):
...
Ben farklı bir yöntem önerdim.
Dikkatlice bakın lütfen.
...

Hangi seçeneklerden bahsediyoruz?

Normalleşme hakkında zaten konuştum. Önce, neden kullanacağımızı ve ancak o zaman nasıl ve nerede kullanacağımızı söyleyin.

Örneğin, yukarıdaki tartışmada bir tür başarı olarak bahsedilen fiyatları neden tam olarak 14 ondalık basamakla karşılaştırdığınızı biliyor olabilirsiniz? :) Size önerdiğim fonksiyonun ComparePrice olduğunu hatırlatmama izin verin. :)
İşte, bu senin mi? Doğru alıntı mı yapıyorum?
Irtron 10.09.2007 04:07

...

int KarşılaştırmaFiyat(çift a, çift b)
{
a -= b;
b = Nokta / 2.;
(a > b) ise
dönüş(1);
eğer (a < -b)
dönüş(-1);
dönüş(0);
}
...
Size önerdiğim işlevin ComparePrice olarak adlandırıldığını hatırlatmama izin verin. :)

Dikkat ederseniz, ComparePrice adlı bir fonksiyondan da alıntı yaptım. Sadece sizinki zaten VBAG tarafından değiştirilmiş. Bu yüzden orijinal versiyon hakkında orijinali göz önünde bulundurarak yazdım, yani. senin işlevin!
Her iki işlevi de kendim test ettim. Evet, daha hızlılardı. Ancak karşılaştırmanın güvenilirliği nasıl kontrol edilir? İki çift değişkeni karşılaştırarak kafam çok karıştı? Her ne kadar aralık alındığından beri her şey doğru olmalı! Ama yine de her zaman doğru çalışmayacağına dair şüpheler var!

Normalleşme hakkında zaten konuştum. Önce, neden kullanacağımızı ve ancak o zaman nasıl ve nerede kullanacağımızı söyleyin.

Anahtar soru bu, değil mi? Ben kendim bunu uzun süre düşündüm: "bir duble girersin ve bir duble alırsın " . Ne değişebilir?
Tam cevabı bulamadım. Ama ben böyle hayal ediyorum

çift a = 2.00000000000000
çift b = 2.0000000000001
çift c = 1.999999999999

Tüm bu değişkenler farklıdır ve son karaktere (sayı) kadar bellekte saklanırlar!
Bu durumda işaretleri (sayıları) kendimiz belirleriz. Tanımlanmayan her şey sıfırlarla doldurulur.

Çift a = 2.0 olarak ayarlarsak ve bellekte zaten 2.00001 veya 1.9999999 olarak hatırlanırsa, o zaman NormalizeDouble()'nin o zaman yardımcı olmayacağı açıktır, çünkü zaten kesin olmayan bir değer döndürür!
Bir değişkenin değerini hatırlarken böyle bir hatanın neredeyse hiç olmadığını düşünüyorum. Ayrıca, 2.0 sayısının özellikle 1.9999999999999 olarak hatırlandığını düşünmüyorum, çünkü her karakter (rakam veya nokta) için belleğin bit dizisindeki belirli bir bit yanıtlanacaktır! Yani 2.0 sayısı güvenli bir şekilde 2.00000...00 olarak saklanır.

İşaretleri kendimiz tanımlamadığımız başka bir durum:

bir = 4.0;
b = 2.0;
c = a / b // - "bölme" işlemi işlemci veya daha doğrusu yardımcı işlemci tarafından gerçekleştirilir ve ayrıca değişkeni karakterlerle (sayılar) doldurur.

Ameliyattan sonra şunlara sahip olabilirsiniz:
Sıklıkla:
c = 2.000...0
c= 1.999999999...
c= 2000000001...

onlar. sonuç genellikle gerçek olandan az miktarda farklılık gösterir.

Büyük hatalar çok nadirdir:
c = 2.3

Burada iki açıklama var:
1) a veya b çağrıldığında bit dizisinin bir kısmı bellekte hasar gördü, yani. a ve b değişkenleri değişti.
2) "bölme" işlemi sırasında bir hata oluştu.

Sanırım en sık olan şey 2). Neden bilmiyorum. Bunun, yardımcı işlemcinin çalışmasını ihtiyacın zararına olacak şekilde optimize etmeye çalıştıklarından kaynaklandığını düşünüyorum.

2.000...00 sayısı ile c değişkeni karşılaştırıldığında eşitliğin sağlanmayacağı açıktır. Çünkü tüm bitler eşleşmeyecektir.

Şimdi, NormalizeDouble() yardım etmek için burada!
NormalizeDouble() bu küçük hatayı "düzeltecek"!
Hata genellikle çok küçük olduğundan, küçük bir kesinlikle yuvarlama her zaman doğru sonucu verecektir.

Bunun gibi görünecek:
a = 2.111...11 sayısını ikinci ondalık basamağa yuvarlayalım.
Bunu yapmak için, NormalizeDouble() önce yeni değişkene 2.11 yazar ve kalan bitleri birler değil sıfırlarla doldurur!
Sanırım şöyle görünecek:

double MyNormalizeDouble(double value, int digits)
{
    int factor = MathRound( MathPow(10, digits) ); // factor - это множитель,
                                                      с помощью которого мы из VALUE сделаем целое число
    double result = MathRound(factor * value) / factor;
    
    return(result);
}
Burada, neden NormalizeDouble() gerekli olduğunu elimden geldiğince açıklamaya çalıştım.

Yakın zamana kadar bu açıklama bana tamamen uyuyordu. Ancak son zamanlarda kendim böyle bir planın her zaman işe yaramayacağına ikna oldum.

NormalizeDouble(a, 2) !OC! NormalizeDouble(b, 2), burada !OC! karşılaştırma operatörüdür.
Her ne kadar bence her zaman işe yaramalı!
Bu nedenle, makul ve anlaşılır herhangi bir eleştiriden memnuniyet duyacağım!
 
gravity001 :

Ayrıca, diğer başlıklarda, geliştiricilerin kendileri, çift sabitleri bile karşılaştırmamanın daha iyi olduğunu yazdı !!!
Bu benim için bir haber! Ne denir - soru aslında!
Mümkünse, lütfen bir bağlantı sağlayın!

Geliştiricilere bir sorum var:

Lütfen sabitleri kullanarak çiftleri karşılaştırırken sınırlamaların veya olası sorunların neler olduğunu açıklayın:
1.
çift a=1.23456789;
çift b;

if(a>b) veya if(a<b)

Ve bu formda:
2.
#bir 1.23456789 tanımla;

çift b;

if(a>b) veya if(a<b)
 
gravity001 :

Üstelik orijinal versiyonda, sabit rakamlar yerine şu şekildeydi b = Nokta / 2 - zaten iki normalleştirilmemiş değişkenden ikisi var mı?

Bu nedenle b = Nokta / 2 ifadesini bir sabitle değiştirdim (1. daha az işlem - daha fazla hız 2. sabitlerin açık iletimi - daha yüksek güvenilirlik)

Ancak çifte sabitleri karşılaştırmanın güvenilmezliği hakkındaki açıklamanızın ışığında, bütün mesele kayboluyor. Bu konuyu daha iyi anlamamız gerekiyor.

Geliştiricilerin ne diyeceğini merak ediyorum.
 
VBAG писал (а):
...
Bu benim için bir haber! Ne denir - soru aslında!
Mümkünse, lütfen bir bağlantı sağlayın!
...
Evet link arıyordum, hemen eklemek istedim ama bulamadım! Bir yerde gördüğümü hatırlıyorum ama buna benzer çok konu vardı. Ayrıca diğer forumlarda bir sürü konu okudum, bu konuyla ilgili kitaplardan da okudum.
Bir yerde birinin yazdığını hatırlıyorum, ama nerede olduğunu hatırlamıyorum ((((. Bu nedenle, muhtemelen benim için doğru değildi: "geliştiricilerin kendileri başka başlıklarda yazdı"!
Üzgünüm.
Ama bulursam linkini atarım.

Sanırım bunu bir C++ kitabında okumuştum. Orada gerçek sayıların nasıl karşılaştırılacağı anlatıldı ve orada tamsayılara gitmenin en iyisi olduğu yazılmıştı!
 
gravity001 :
VBAG yazdı:
...
Bu benim için bir haber! Ne denir - soru aslında!
Mümkünse, lütfen bir bağlantı sağlayın!
...
Evet link arıyordum, hemen eklemek istedim ama bulamadım! Bir yerde gördüğümü hatırlıyorum ama buna benzer çok konu vardı. Ayrıca diğer forumlarda bir sürü konu okudum, bu konuyla ilgili kitaplardan da okudum.
Bir yerde birinin yazdığını hatırlıyorum, ama nerede olduğunu hatırlamıyorum ((((. Bu nedenle, muhtemelen benim için doğru değildi: "geliştiricilerin kendileri başka başlıklarda yazdı"!
Üzgünüm.
Ama bulursam linkini atarım.

Sanırım bunu bir C++ kitabında okumuştum. Orada gerçek sayıların nasıl karşılaştırılacağı anlatıldı ve orada tamsayılara gitmenin en iyisi olduğu yazılmıştı!
Katılımınız ve yardımlarınız için teşekkür ederiz. Maalesef programlama alanında akademik bilgiye sahip değilim. Bu nedenle, daha fazla dinlemeli ve hatırlamalısınız. Ve umarım geliştiriciler soruma cevap verir ve açıklığa kavuşturur.
Geliştiricilere bir sorum var:

Lütfen sabitleri kullanarak çiftleri karşılaştırırken sınırlamaların veya olası sorunların neler olduğunu açıklayın:
1.
çift a=1.23456789;
çift b;

if(a>b) veya if(a<b)

Ve bu formda:
2.
#bir 1.23456789 tanımla;

çift b;

if(a>b) veya if(a<b)
 
Bu tür problemler 1.3333+0.0004 != 1.3337
 

Bu konuşma sonsuza kadar devam edecek gibi görünüyor. Yeni bir kullanıcı uygun deneyimi ve bilgiyi elde edene kadar, kural olarak, birkaç kez normalleştirmeye girmeyi başarır.

Belki de, MT5'te, karşılaştırma işlemleri gerçekleştirirken gerçek sayıların doğruluğunu zorla, örneğin 8 ondalık basamakla sınırlamak mantıklıdır (yani, NormalizeDouble'ı () basamak=8 ile yürütülmeye zorlamak). Ve yalnızca NormalizeDouble() işlevi açıkça belirtilmişse, içinde belirtilen parametrelere göre normalleştirmeyi gerçekleştirin. Bu durumda, soru çok daha az sıklıkta, yani yalnızca kullanıcı tam olarak belirtilen doğruluğa ihtiyaç duyduğunda ortaya çıkacaktır. Bence bu yaban turpu biraz da olsa turptan daha tatlı.

 
VBAG :
Merhaba!
Bildiğiniz gibi sadece hesaplamaların doğruluğu değil, yazılan kodun güvenilirliği de programlama stiline ve kodun doğruluğuna bağlıdır.
Oyuncak yazmıyoruz ve bu nedenle yazılı programın güvenilirliği ilk gereksinimdir. Hesaplamaların çoğu çiftler halinde yapılır ve doğru karşılaştırma koddadır.
iki gerçek sayının programları, belirli bir yaklaşım ve doğruluk gerektirir.
"Doğru" programlama stilini bulmaya çalışıyorum. Dolayısıyla soru:

İfade için

çift a;
çift b;

if(a==b) veya if(a!=b)
{......} {.... ..}

geliştiriciler tavsiye ediyor
//+------------------------------------------- --------------------+
//| İki gerçek sayıyı karşılaştırma işlevi. |
//+------------------------------------------- --------------------+
bool CompareDouble(çift Sayı1, çift Sayı2)
{
bool Karşılaştır = NormalizeDouble(Sayı1 - Sayı2, 8) == 0;
dön(karşılaştır);
}
//+------------------------------------------- --------------------+


Kod doğru mu?

çift a;
çift b;

if(a>b) if(a<b)
{......} {......}


Büyük olasılıkla genel durumda değil. Hangi doğru doğrulama yöntemi seçilmelidir?
Çiftlerle çalışmanın en iyi tarzı nedir?
Cevap veren herkese şimdiden teşekkürler.

Ödüllü... :)

Float karşılaştırması - fark modülünü küçük bir eşik ile karşılaştırarak yapılır.

dönüş (fabs(d1-d2) < 1e-10) örneğin.

Suları neden bulandırıyor... Güzel raporlar için NormalizeDouble (...) işlevi gereklidir, başka bir şey değil.