2010-05-01 4 views
170

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

Например:

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"). Если значение десятичной точки отсутствует, то я не хочу это показывать.

ответ

306

Для чисел с плавающей запятой 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 Лопес упомянуто ниже, в сравнении с небольшим значением epsilon будет отбрасывать с плавающей точкой вычислений MIS-вычислений. Поскольку речь идет о double значения, ниже будет более расчет с плавающей точкой доказательство Ответ:

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

Это работает, когда число начинается как целое число, но не обязательно, когда число является результатом некоторых плавающей точки вычислений. Как насчет чего-то вроде «(d% 1)

+7

Жаль, что лучший ответ в этом потоке - комментарий, а не принятый ответ. Хороший Адриан. – starskythehutch

+0

Ответ, данный @MarkRushakoff, не подходит для ввода типа '2.719601835756618E9', который является двойным –

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

Problemo Солво.

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

+3

или просто 'return ceil (num) == num && floor (num) == num;' –

+8

или просто 'return ceil (num) == floor (num);' – gregsdennis

42

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

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

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

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

Будет ли один из них быстрее, чем другой? Я хочу сделать это в контексте, чувствительном к производительности. – Basil

+0

@Basil - зависит от обстоятельств. Вы должны сделать некоторые тайминги для себя и судить. –

+4

'Math.Abs ​​(d- (int) d) cgTag

12

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

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); 
} 
12

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

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

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

Выход:

1 
1.02 
+0

@Mark Звучит интересно. У вас есть пример формата, который разделяет конечные нули? –

+0

Я согласен с тем, что это безопаснее и что OP должен делать, но это не ответ на более узкий (но более интересный) вопрос о том, имеет ли значение дробную часть или нет. – Clifford

+3

@Clifford: Обычно я пытаюсь ответить на основе того, что лучше всего решить проблему OPs, а не на основе названия. Титулы редко являются точным описанием проблемы. –

2

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

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" 

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

+1

Это не относится к вопросу определения того, имеет ли значение не дробную часть, что является математическим вопросом. Однако, вероятно, именно то, что требуется ОП, дает его пояснительная записка. – Clifford

+2

Да, он хочет просто форматировать двойное или десятичное значение без десятичной точки. Спасибо ... –

2

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

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

и

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

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

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

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

Вот мой код для возврата 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.

+4

Предполагается, что вы работаете с одной культурой. Например, он не будет работать должным образом с культурами, которые представляют десятичные числа, такие как 1.000,00 –

3

Если верхняя и нижняя граница Int32 вопросов:

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

Простое и понятное решение! Ницца! –

-1

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

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

Это ужасное решение. – Ospho

-1

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

int.TryParse() 

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

+0

Аргумент для int.TryParse - это строка, а не двойная. –

+0

'yourDouble.toString (" G17 ")' – BackDoorNoBaby

1
static bool IsWholeNumber(double x) 
{ 
    return Math.Abs(x % 1) < double.Epsilon; 
} 
Смежные вопросы