Вопрос

Следующий код в C # не работает:

int iValue = 0;
double dValue = 0.0;

bool isEqual = iValue.Equals(dValue);

Итак, вопрос: как лучше сравнить Double и Int?

Это было полезно?

Решение

Вы действительно не можете сравнивать значения с плавающей запятой и интегральные значения наивным способом; в частности, поскольку существует классическая плавающая точка проблемы с представлением . Что вы можете сделать, так это вычесть одно из другого и посмотреть, меньше ли разница между ними, чем какая-то точность, о которой вы заботитесь, например:

int iValue = 0;
double dValue = 0.0;

var diff = Math.Abs(dvalue - iValue);
if( diff < 0.0000001 ) // need some min threshold to compare floating points
   return true; // items equal

Вы действительно должны определить для себя, что для вас означает равенство . Например, вы можете захотеть, чтобы значение с плавающей запятой округлялось до ближайшего целого числа, чтобы значение 3.999999981 было «равно». до 4. Или вы можете захотеть усечь значение, чтобы оно было равно 3. Все зависит от того, чего вы пытаетесь достичь.

РЕДАКТИРОВАТЬ . Обратите внимание, что я выбрал 0,0000001 в качестве порогового значения в качестве примера ... вам нужно решить для себя, какая точность достаточна для сравнения. Просто поймите, что вы должны находиться в пределах нормальных представительных границ double , которые, как я считаю, определены как Double.Epsilon .

Другие советы

Чрезвычайно плохая идея сравнивать целые числа и числа с плавающей точкой на равенство в любом языке. Он работает для очень простых случаев, но после того, как вы все сделаете, математическая обработка программы значительно снизится.

Это связано с тем, как числа с плавающей запятой хранятся в двоичной цифровой системе.

Если вы уверены, что хотите использовать это, создайте класс, чтобы сделать свой собственный номер с дробями. используйте одно целое, чтобы сохранить целое число, и другое, чтобы сохранить дробь.

Это действительно зависит от того, что вы считаете "равным". Если вы хотите, чтобы ваше сравнение возвращало true тогда и только тогда, когда double точно соответствует целочисленному значению (т. Е. Не имеет дробного компонента), вы должны привести int к double, чтобы выполнить сравнение:

bool isEqual = (double)iValue == dValue;

Если что-то вроде 1.1 будет считаться равным 1, вы можете либо привести двойное число к целому (если вы хотите полностью игнорировать дробный компонент), либо округлить двойное, если хотите, чтобы 1,9 было равно 2.

double val1 = 0;
double val2 = 0.0;
if((val1 - Double.Epsilon) < 0)
{
    // Put your code here
}

      OR

if((val2 - Double.Epsilon) < 0)
{
    // Put your code here
}

где Double.Epsilon - наименьшее возможное значение для Double.

В настоящее время практически единственный раз, когда нужно сравнивать значения типов double и integer или long для строгого равенства, это когда, по какой-то причине один застревает, сохраняя или передавая целочисленные величины в виде значений с плавающей запятой, и позже необходимо преобразовать их обратно. Такое преобразование в большинстве случаев проще всего выполнить, приведя целочисленный тип к double , а затем сравнив результат этого приведения. Обратите внимание, что преобразование из long в double может быть неточным, если число находится вне диапазона ± 2 52 . Тем не менее, за несколько дней до того, как стало доступно 64-битное long , double было удобным типом хранения для целочисленных величин, которые были слишком велики для 32-битного int но достаточно маленький, чтобы обрабатываться double .

Обратите внимание, что преобразование long в double и последующее сравнение приведут к " равному " результат, если номинальное значение double точно не соответствует значению long , но представляет наиболее близкое возможное значение double к этому значению. Такое поведение имеет смысл, если признать, что типы с плавающей точкой на самом деле представляют не одно точное значение, а диапазон значений.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top