2010-11-02 3 views
18

Possible Duplicate:
How to determine if a decimal/double is an integer?Что такое хороший способ проверить, является ли double целым числом на C#?

У меня есть переменная типа double, и я хочу проверить, является ли это целым числом.

На данный момент у меня

public bool CheckIfInteger(double number) 
{ 
    return number.ToString().Contains(".") == false; 
} 

Есть ли лучший способ?

ОБНОВЛЕНИЕ: Извините, я не осознавал потенциал путаницы, целым числом я имел в виду математическое определение целого числа, то есть натуральные числа вместе с отрицаниями ненулевых натуральных чисел.

+8

Ваш способ рискован: что, если в региональных настройках машины есть «,» как разделитель десятичных чисел? Похоже, вы можете выбрать один из ответов ниже. :) –

+0

Первое, что приходит в голову с использованием текущего подхода, который вы используете, состоит в том, что он не может учитывать, что разделитель десятичных чисел может быть различным в зависимости от текущей культуры потоков. Если вы собираетесь выбрать один из альтернатив из приведенных ниже ответов, будьте внимательны ко всему, что относится к входному номеру в виде строки, прежде чем дать вам результат ... особенно если он не учитывает десятичные разделители, отличные от «.». –

+0

@Shadow: Вы можете обходиться с помощью 'CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator'. Но как насчет '((десятичный)) Int32.MaxValue + 1)'? Это десятичное без десятичного разделителя. – abatishchev

ответ

29
return Math.Truncate(number) == number; 

Как уже упоминалось в комментариях, возможно, потребуется принять во внимание тот факт, что double представление вашего номера не может быть точным числом. В этом случае вам необходимо учесть некоторые ошибки Маржа-оф-:

double diff = Math.Abs(Math.Truncate(number) - number); 
return (diff < 0.0000001) || (diff > 0.9999999); 
+7

Однако следует помнить о проблемах с плавающей запятой: с 'double number = 100.0 * (8183.23 - 6695.37)' вы получите 'false', используя этот метод. –

6

Try:

public bool CheckIfInteger(double number) 
{ 
    return ((double) (int) number == number); 
} 

Или хорошеет:

public bool CheckIfInteger(double number) 
{ 
    return (Math.Floor(number) == number); 
} 
+0

Почему вы снова бросаете назад обратно? – nawfal

24

Если вы хотите проверить, для Integer, это будет сделать это:

public bool IsInteger(double number) 
{ 
    return (number % 1 == 0); 
} 

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

public bool IsInt32(double number) 
{ 
    return (number % 1 == 0) && number >= Int32.MinValue && number <= Int32.MaxValue; 
} 
+3

это не будет работать в случае больших двойных значений, диапазон значений double больше, чем диапазон значений int. TryParse даст вам false из-за диапазона, но ваш мода вернет true. Попробуйте с double.MaxValue – BrokenGlass

+0

Спасибо за примечание, обновил мой ответ. –

+0

@BrokenGlass, @Tim: вопрос говорит «integer», а не «int» или «Int32». Исходная логика Тима была правильной в том, что она соответствовала тому, что OP пытается в вопросе, возвращая true для любого целого 'double', иначе false. (В идеале OP должен прояснить, означают ли они «Int32» или просто целое число.) – LukeH

4

Я хотел бы использовать TryParse:

double value = 2.0; 
    int number; 
    bool result = Int32.TryParse(value.ToString(), out number); 
0

Я использую следующий метод расширения строки, которая проверяет против шаблона RegEx

public static bool IsInteger(this string inputString) 
    { 
     Regex regexInteger = new Regex(@"^[-]?\d+$"); 
     Match m = regexInteger.Match(inputString); 
     return m.Success; 
    } 
+5

это не будет работать во многих случаях, включая переполнение, диапазон значений double больше, чем диапазон значений int. Теперь у вас есть две проблемы. – BrokenGlass

+0

Справедливый комментарий - согласовано – Madeleine

+1

Будет ли это также терпеть неудачу, если отрицательное число не выражается как -1, а как (1)? –

15

ловушка работы с строковыми представлениями локаль используется и yoou должен заботиться о округлении вопросов. 0.999999999 можно рассматривать как целое число 1 в большинстве случаев. Вот небольшой фрагмент кода с учетом округления ошибок:

Math.Abs(number - Math.Round(number)) < EPSILON 

где EPSILON является двойным значением, которое достаточно мал для вашей цели 0.00001, например

Смотрите также это для более определенной информации: http://msdn.microsoft.com/en-us/library/system.double.epsilon.aspx

+5

+1 для упоминания эпсилон. – Polyfun

2
public static bool CheckIfInteger(double number) 
    { 
     return number - Math.Truncate(number) == 0; 
    } 
+2

Как насчет числа == Math.Truncate (number)? – JohannesH

2

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

return Math.Abs(someDouble - Math.Round(someDouble)) < TOLERANCE; 
1

Я нравится идея abatishchev, чтобы использовать CurrentCulture.

Это не решит проблему эпсилона (которую я даже не рассматривал изначально)?

Смежные вопросы