Какой самый надежный способ проверить, является ли переменная с плавающей запятой целым числом? - PullRequest
1 голос
/ 12 марта 2009

Я могу придумать несколько способов, например.

Convert.ToInt32(floatingPoint) - floatingPoint == 0;
Math.Truncate(floatingPoint) - floatingPoint == 0;
floatingPoint % 1 == 0;
Math.Floor(floatingPoint) == floatingPoint;
//etc...

Но какой метод наиболее надежен?

Ответы [ 6 ]

5 голосов
/ 12 марта 2009

Вы не должны проверять точное равенство нулю, поскольку число с плавающей запятой обычно содержит только самое близкое приближение к числу, которое вы ему присвоили.

Например, наиболее близким возможным значением 42, которое может представлять тип, может быть что-то вроде 42.00000000000000662, которое вы все равно хотели бы считать целым значением.

Возьмите разницу между значением и округленным значением, затем возьмите его абсолютное значение (чтобы оно не было отрицательным) и сравните с небольшим значением:

if (Math.Abs(Math.Round(floatingPoint) - floatingPoint) < 0.000001) ...
2 голосов
/ 12 марта 2009

Плавающие точки не могут точно представлять некоторые целые числа, поэтому не существует метода, который был бы действительно надежным . В частности, любой int, который больше 2 ^ 24, не может быть точно представлен как float. Увы, это часть цены, которую вы платите за использование представления с плавающей точкой!

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

1 голос
/ 12 марта 2009

Нет обычно надежного метода.

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

Вы должны учитывать диапазон и точность значений fp и int, с которыми вы имеете дело. Все зависит от того, чего вы пытаетесь достичь.

У Guffa хороший подход, использующий допустимый диапазон точности для сравнения int.

1 голос
/ 12 марта 2009

Вы столкнетесь с классической проблемой чисел с плавающей точкой, являющихся только приближениями. Если вы сделаете это:

floatingPoint = 1.0/3.0;
floatingPoint *= 3;

у вас получится что-то близкое, но не совсем 1.

1 голос
/ 12 марта 2009

Независимо от надежности, метод по модулю выглядит простым для понимания (не нужно читать какие-либо спецификации) и быстрым (без вызова функции).

0 голосов
/ 12 марта 2009

Целые числа могут быть представлены точно в представлении с плавающей запятой, поэтому любой из них должен работать, если вы проверяете точное целое число (лично я бы использовал первое ...)

...