Разработчикам - вычисления MathCeil, MathFloor

 
Код эксперта для проверки, с пояснениями, и собственно сам вопрос (последний билд)
bool t = true;
int start()
  {
double X1 = 0.780; // фанарные числа
double Y1 = 0.684;
double X2 = 0.684;
double Y2 = 0.780;

double H = 20.0;

if (t) 
    {
     double N1,N2;
     N1 = (X1 - Y1)/(H * Point);
     N2 = (X2 - Y2)/(H * Point);

     Print("функция Print() по-разному печатает в журнал double переменные через разделитель (,) и (+)");
     Print("исходное число N1 (вычисленно из других чисел) = ", N1, " разделитель (,)"); 
     Print("исходное число N2 (вычисленно из других чисел) = " + N2 + " разделитель(+)"); 

     double P1 = 48.0;
     double P2 = -48.0;
     Print("исходное число P1 (начальное) = ", P1); 
     Print("исходное число P2 (начальное) = ", P2); 
     
     Print("--------------");

     Print("ошибка сравнения double переменных if (N1 != P1) и if (N2 != P2)");
     if (N1 != P1)
         {
          Print(N1, " != ", P1);
          }
     if (N2 != P2)
         {
          Print(N2, " != ", P2);
          }
          
          Print("--------------");
          
          Print("ошибка функции MathFloor(), применительно к числу N");
          Print("число N1 = ", N1, ", число N1 после MathCeil = ", MathCeil(N1));
          Print("число N1 = ", N1, ", число N1 после MathFloor = ", MathFloor(N1));

          Print("число P1 = ", P1, ", число P1 после MathCeil = ", MathCeil(P1));
          Print("число P1 = ", P1, ", число P1 после MathFloor = ", MathFloor(P1));
          
          Print("--------------");
          
          Print("ошибка функции MathCeil(), применительно к числу N");
          Print("число N2 = ", N2, ", число N2 после MathCeil = ", MathCeil(N2));
          Print("число N2 = ", N2, ", число N2 после MathFloor = ", MathFloor(N2));

          Print("число P2 = ", P2, ", число P2 после MathCeil = ", MathCeil(P2));
          Print("число P2 = ", P2, ", число P2 после MathFloor = ", MathFloor(P2));
     
     t= false;
     }
   return(0);
  }


вот результат, где и так все видно.
???????????????????????????????????

18:27:43 XXX AUDUSD,M1: loaded successfully
18:27:44 XXX started for testing
18:27:44 2004.06.15 23:42  XXX AUDUSD,M1: функция Print() по-разному печатает в журнал double переменные через разделитель (,) и (+)
18:27:44 2004.06.15 23:42  XXX AUDUSD,M1: исходное число N1 (вычисленно из других чисел) = 48 разделитель (,)
18:27:44 2004.06.15 23:42  XXX AUDUSD,M1: исходное число N2 (вычисленно из других чисел) = -48.00000000 разделитель(+)
18:27:44 2004.06.15 23:42  XXX AUDUSD,M1: исходное число P1 (начальное) = 48
18:27:44 2004.06.15 23:42  XXX AUDUSD,M1: исходное число P2 (начальное) = -48
18:27:44 2004.06.15 23:42  XXX AUDUSD,M1: --------------
18:27:44 2004.06.15 23:42  XXX AUDUSD,M1: ошибка сравнения double переменных if (N1 != P1) и if (N2 != P2)
18:27:44 2004.06.15 23:42  XXX AUDUSD,M1: 48 != 48
18:27:44 2004.06.15 23:42  XXX AUDUSD,M1: -48 != -48
18:27:44 2004.06.15 23:42  XXX AUDUSD,M1: --------------
18:27:44 2004.06.15 23:42  XXX AUDUSD,M1: ошибка функции MathFloor(), применительно к числу N
18:27:44 2004.06.15 23:42  XXX AUDUSD,M1: число N1 = 48, число N1 после MathCeil = 48
18:27:44 2004.06.15 23:42  XXX AUDUSD,M1: число N1 = 48, число N1 после MathFloor = 47
18:27:44 2004.06.15 23:42  XXX AUDUSD,M1: число P1 = 48, число P1 после MathCeil = 48
18:27:44 2004.06.15 23:42  XXX AUDUSD,M1: число P1 = 48, число P1 после MathFloor = 48
18:27:44 2004.06.15 23:42  XXX AUDUSD,M1: --------------
18:27:44 2004.06.15 23:42  XXX AUDUSD,M1: ошибка функции MathCeil(), применительно к числу N
18:27:44 2004.06.15 23:42  XXX AUDUSD,M1: число N2 = -48, число N2 после MathCeil = -47
18:27:44 2004.06.15 23:42  XXX AUDUSD,M1: число N2 = -48, число N2 после MathFloor = -48
18:27:44 2004.06.15 23:42  XXX AUDUSD,M1: число P2 = -48, число P2 после MathCeil = -48
18:27:44 2004.06.15 23:42  XXX AUDUSD,M1: число P2 = -48, число P2 после MathFloor = -48
 
Спасибо за проведенные исследования.
К счастью, результаты MQL4 расчетов 100% верны.

Перенесем код в C/C++ компилятор (взят Visual C++ 6.0):
int main()
  {
   double X1=0.780; // фанарные числа
   double Y1=0.684;
   double X2=0.684;
   double Y2=0.780;

   double H=20.0;
   double Point=0.0001;
   double N1,N2;
//----
   N1=(X1-Y1)/(H * Point);
   N2=(X2-Y2)/(H * Point);

     double P1=48.0;
     double P2=-48.0;
     printf("исходное число P1 (начальное) = %lf\n", P1);
     printf("исходное число P2 (начальное) = %lf\n", P2);

     printf("--------------\n");

     printf("ошибка сравнения double переменных if (N1 != P1) и if (N2 != P2)\n");
     if(N1!=P1) printf("%lf != %lf\n",N1,P1);
     if(N2!=P2) printf("%lf != %lf\n", N2, P2);

     printf("--------------\n");

     printf("ошибка функции MathFloor(), применительно к числу N\n");
     printf("число N1 = %lf , число N1 после MathCeil = %lf\n",N1, ceil(N1));
     printf("число N1 = %lf , число N1 после MathFloor = %lf\n",N1, floor(N1));

     printf("число P1 = %lf , число P1 после MathCeil = %lf\n", P1,ceil(P1));
     printf("число P1 = %lf , число P1 после MathFloor = %lf\n",P1,floor(P1));

     printf("--------------\n");

     printf("ошибка функции MathCeil(), применительно к числу N\n");
     printf("число N2 = %lf , число N2 после MathCeil = %lf\n", N2,ceil(N2));
     printf("число N2 = %lf , число N2 после MathFloor = %lf\n", N2,floor(N2));

     printf("число P2 = %lf , число P2 после MathCeil = %lf\n", P2,ceil(P2));
     printf("число P2 = %lf , число P2 после MathFloor = %lf\n",P2,floor(P2));
//----
   return(0);
  }



Запустим и получим точно такой же результат, что и в MQL4:

исходное число P1 (начальное) = 48.000000
исходное число P2 (начальное) = -48.000000
--------------
ошибка сравнения double переменных if (N1 != P1) и if (N2 != P2)
48.000000 != 48.000000
-48.000000 != -48.000000
--------------
ошибка функции MathFloor(), применительно к числу N
число N1 = 48.000000 , число N1 после MathCeil = 48.000000
число N1 = 48.000000 , число N1 после MathFloor = 47.000000
число P1 = 48.000000 , число P1 после MathCeil = 48.000000
число P1 = 48.000000 , число P1 после MathFloor = 48.000000
--------------
ошибка функции MathCeil(), применительно к числу N
число N2 = -48.000000 , число N2 после MathCeil = -47.000000
число N2 = -48.000000 , число N2 после MathFloor = -48.000000
число P2 = -48.000000 , число P2 после MathCeil = -48.000000
число P2 = -48.000000 , число P2 после MathFloor = -48.000000



Такие вопросы периодически возникают в форуме и связаны они с тем, что операции сравнения с вещественными числами имеют ряд особенностей из-за потери точности. То, что числа до 5-6 разряда выглядят одинаково, не значит, что они на самом деле одинаковы.

На всякий случай повторю: ошибок тут нет вообще.

 
То, что числа до 5-6 разряда выглядят одинаково, не значит, что они на самом деле одинаковы.

Правильно ли полагать, что нормализация до 4 знака полностью решает эту проблему?
 
То, что числа до 5-6 разряда выглядят одинаково, не значит, что они на самом деле одинаковы.

Правильно ли полагать, что нормализация до 4 знака полностью решает эту проблему?

Нормализация перед сравнением должна решать проблему сравнения.
Главное, не использовать "сырое" сравнение вещественных чисел.
 

Нормализация перед сравнением должна решать проблему сравнения.
Главное, не использовать "сырое" сравнение вещественных чисел.

Действительно ТАК!!!
Предложение, раз уж сравнивать приходиться очень часто и почти всегда, написать в хелпе большими буквами что-то вроде текста выше, а еще лучше где-нибудь на рамке эдитора, при попытке юзера что-либо сравнить (<>=) появляестя та самая надпись, и начинает мигать как сумасшедшая, менять цвета, нагнетать страх и ужас, производить зловещие звуки, тренд превращается в голодного змея и набрасывается на мышку ЫЫЫЫЫЫЫ, чуть руку не отгрыз :) оу, чего это я, ночные кошмары замучали......

Спасибо за объяснение. С уважением.
 
Renat,
ОК, спасибо.
Причина обращения: