Вот одна ошибка, с которой я сталкиваюсь каждые несколько месяцев:
double x = 19.08;
double y = 2.01;
double result = 21.09;
if (x + y == result)
{
MessageBox.Show("x equals y");
}
else
{
MessageBox.Show("that shouldn't happen!"); // <-- this code fires
}
Можно предположить, что в коде отображается «x равно y», но это не так.
Краткое объяснение состоит в том, что десятичные разряды, представленные в виде двоичной цифры, не вписываются в двойные.
Пример:
2.625 будет выглядеть так:
10,101
потому что
1-------0-------1---------0----------1
1 * 2 + 0 * 1 + 1 * 0.5 + 0 * 0.25 + 1 * 0,125 = 2.65
И некоторые значения (например, результат 19.08 плюс 2.01) не могут быть представлены двоичными разрядами.
Одним из решений является использование константы:
double x = 19.08;
double y = 2.01;
double result = 21.09;
double EPSILON = 10E-10;
if ( x + y - result < EPSILON )
{
MessageBox.Show("x equals y"); // <-- this code fires
}
else
{
MessageBox.Show("that shouldn't happen!");
}
Если в первом примере я использую десятичное число вместо двойного, результатом будет «x равно y».
Но я спрашиваю себя, не является ли это из-за того, что «десятичный» тип не уязвим к этому поведению, или он просто работает в этом случае, потому что значения «вписываются» в 128-битное.
Может быть, у кого-то есть лучшее решение, чем использование константы?
Btw. это не проблема dotNet / C #, я думаю, что это происходит в большинстве языков программирования.