Основы языка
© 2000-2011, MetaQuotes Software Corp.
59
записываются в десятичной системе, в двоичной системе можно записать только в виде
бесконечной дроби.
Например, числа 0.3 и 0.7 представлены в компьютере бесконечными дробями, в то время как
число 0.25 хранится точно, так как представляет из себя степень двойки.
В связи с этим, категорически не рекомендуется сравнивать между собой два вещественных
числа на равенство, так как такое сравнение не является корректным.
Пример:
void OnStart()
{
//---
double three=3.0;
double x,y,z;
x=1/three;
y=4/three;
z=5/three;
if(x+y==z) Print("1/3 + 4/3 == 5/3");
else Print("1/3 + 4/3 != 5/3");
// Результат: 1/3 + 4/3 != 5/3
}
Если все же необходимо сравнить на равенство два вещественных числа, то можно сделать это
двумя разными способами. Первый способ заключается в сравнении разницы между двумя
числами с какой-то малой величиной, задающей точность сравнения.
Пример:
bool EqualDoubles(double d1,double d2,double epsilon)
{
if(epsilon<0) epsilon=-epsilon;
//---
if(d1-d2>epsilon) return false;
if(d1-d2<-epsilon) return false;
//---
return true;
}
void OnStart()
{
double d_val=0.7;
float f_val=0.7;
if(EqualDoubles(d_val,f_val,0.000000000000001)) Print(d_val,"equals",f_val);
else Print("Different: d_val = ",DoubleToString(d_val,16),
" f_val = ",DoubleToString(f_val,16));
// Результат: Different: d_val= 0.7000000000000000 f_val= 0.6999999880790710
}
Необходимо отметить, что значение параметра epsilon в приведенном примере не может быть
меньше предопределенной константы DBL_EPSILON. Значение этой константы
2.2204460492503131e-016. Для типа float соответствующая константа FLT_EPSILON =
1.192092896e-07. Смысл этих значений таков, что это наименьшее значение, удовлетворяющее
условию 1.0+DBL_EPSILON != 1.0 (для чисел типа float 1.0+FLT_EPSILON != 1.0).
Второй способ предполагает сравнивать нормализованную разность двух вещественных чисел с
нулевым значением. Сравнивать разность нормализованных чисел с нулём бесполезно, так как в