Как определить, является ли десятичное/двойное целое?

Как определить, является ли десятичное или двойное значение целым числом?

Например:

decimal d = 5.0; // Would be true
decimal f = 5.5; // Would be false

или

double d = 5.0; // Would be true
double f = 5.5; // Would be false

Я хотел бы знать, что это так, что я могу определить программно, если я хочу вывести значение с помощью .ToString("N0") или .ToString("N2"). Если значение десятичной точки отсутствует, то я не хочу это показывать.

Ответ 1

Для чисел с плавающей запятой n % 1 == 0 обычно является способом проверить, нет ли чего-либо за десятичной точкой.

    public static void Main (string[] args)
    {
        decimal d = 3.1M;
        Console.WriteLine((d % 1) == 0);
        d = 3.0M;
        Console.WriteLine((d % 1) == 0);
    }

Вывод:

False
True

Обновление: Как упоминалось ниже @Adrian Lopez, сравнение с небольшим значением epsilon отбрасывает неверные вычисления вычисления с плавающей запятой. Поскольку вопрос касается значений double, ниже будет более надежный ответ вычисления с плавающей запятой:

Math.Abs(d % 1) <= (Double.Epsilon * 100)

Ответ 2

Существует несколько способов сделать это. Например:

double d = 5.0;
bool isInt = d == (int)d;

Вы также можете использовать modulo.

double d = 5.0;
bool isInt = d % 1 == 0;

Ответ 3

Как насчет этого?

public static bool IsInteger(double number) {
    return number == Math.Truncate(number);
}

Тот же код для decimal.

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

public static bool IsNearlyInteger(double number) {
    return Math.Round(number, 2) == Math.Round(number);
}

Ответ 4

Хотя предлагаемые решения, похоже, работают на простых примерах, делать это в целом - плохая идея. Число может быть не точно целым числом, но когда вы пытаетесь отформатировать его, оно достаточно близко к целому числу, которое вы получаете 1.000000. Это может произойти, если вы сделаете расчет, который теоретически должен дать ровно 1, но на практике дает число, очень близкое, но не равное одному из-за ошибок округления.

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

double d = 1.0002;
Console.WriteLine(d.ToString("0.##"));
d = 1.02;
Console.WriteLine(d.ToString("0.##"));

Вывод:

1
1.02

Ответ 5

bool IsInteger(double num) {
    if (ceil(num) == num && floor(num) == num)
        return true;
    else
        return false;
}

Проблема solvo.

Редактировать: Pwned by Mark Rushakoff.

Ответ 6

Если верхняя и нижняя граница Int32 имеет значение:

public bool IsInt32(double value)
{
    return value == (int)value && value >= int.MinValue && value <= int.MaxValue;
}

Ответ 7

Вы можете использовать форматирование строк для двойного типа. Вот пример:

double val = 58.6547;
String.Format("{0:0.##}", val);      
//Output: "58.65"

double val = 58.6;
String.Format("{0:0.##}", val);      
//Output: "58.6"

double val = 58.0;
String.Format("{0:0.##}", val);      
//Output: "58"

Сообщите мне, если это не поможет.

Ответ 8

Ответ Марку Рушакова может быть проще, но следующее также работает и может быть более эффективным, поскольку не существует неявной операции деления:

     bool isInteger = (double)((int)f) == f ;

и

     bool isInteger = (decimal)((int)d) == d ;

Если вам нужно одно выражение для обоих типов, возможно,

     bool isInteger = (double)((int)val) == (double)val ;

Ответ 9

static bool IsWholeNumber(double x) 
{
    return Math.Abs(x % 1) < double.Epsilon;
}

Ответ 10

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

Здесь мой код возвращает true, если строка "s" представляет числовое число с не более чем двумя десятичными знаками, а false в противном случае. Это позволяет избежать любых проблем, которые могут возникнуть в результате неточности значений с плавающей запятой.

try
{
    // must be numeric value
    double d = double.Parse(s);
    // max of two decimal places
    if (s.IndexOf(".") >= 0)
    {
        if (s.Length > s.IndexOf(".") + 3)
            return false;
    }
    return true;
catch
{
    return false;
}

Я более подробно об этом расскажу в http://progblog10.blogspot.com/2011/04/determining-whether-numeric-value-has.html.

Ответ 11

Возможно, это не самое элегантное решение, но оно работает, если вы не слишком придирчивы!

bool IsInteger(double num) {
    return !num.ToString("0.################").Contains(".");
}

Ответ 12

Вы можете использовать метод TryParse.

int.TryParse()

Это проверяет, можно ли преобразовать значение в целое целое число. Затем результат может указывать флаг, который можно использовать в другом месте вашего кода.

Ответ 13

Попробуйте следующее:

number == Convert.ToInt16(number);