20

Possible Duplicate:
How to determine if a decimal/double is an integer?

I have a variable of type double and am wanting to check whether it is an integer.

At the moment I have

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

Is there a better way?

UPDATE: Sorry I didn't realise the potential for confusion, by integer I meant the mathematical definiton of integer, that is the natural numbers together with the negatives of the non-zero natural numbers.

Community
  • 1
  • 1
Simon
  • 1,499
  • 3
  • 17
  • 23
  • 8
    Your way is risky: what if the machine regional settings has "," as decimal separator? Looks like you can choose from the answers below. :) – Shadow The GPT Wizard Nov 02 '10 at 11:44
  • The first thing that comes to mind with the current approach you use is that it might not take into account that the decimal separator could be different depending on the current thread culture. If you're going to choose one of the alternatives from the answers below be careful of anything that treats the input number as a string before giving you a result... especially if it does not account for decimal separators other than "." – Saul Dolgin Nov 02 '10 at 11:50
  • @Shadow: You case can be workarounded with `CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator`. But what about `((decimal))Int32.MaxValue+1)`? It's a decimal without decimal separator – abatishchev Nov 02 '10 at 12:06
  • kinda cool to see all the creative solutions to such a basic problem. cheers. – tenfour Nov 02 '10 at 12:53
  • Not to be pedantic, but...A Double will never be an Integer. The value of a Double might very well be integral. I think you mean "if a Double has an integral value" ? – MickeyfAgain_BeforeExitOfSO Nov 03 '10 at 15:04
  • @mickeyf If that's not to be pedantic, then what is it to be? In any case, it's wrong ... integer is a mathematical concept, not a type in C# (which has int, aliased by System.Int32) -- the OP correctly didn't capitalize it, and you wrongly did. The value of a double (which is aliased by System.Double) can be an integer, which is exactly the same thing as a double having an integral value. – Jim Balter Mar 30 '16 at 00:03

9 Answers9

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

As mentioned in the comments, you might need to take account of the fact that a double representation of your number might not be an exact integer. In that case you'll need to allow for some margin-of-error:

double diff = Math.Abs(Math.Truncate(number) - number);
return (diff < 0.0000001) || (diff > 0.9999999);
LukeH
  • 263,068
  • 57
  • 365
  • 409
  • 7
    However, be aware of floating point precision issues: with `double number = 100.0 * (8183.23 - 6695.37)` you would get `false` using this method. – Dirk Vollmar Nov 02 '10 at 12:20
  • Why use Truncate, rather than Round? With Round you only need to test against the small limit and not the big one. Example: – Jan Heldal Feb 04 '21 at 21:38
  • (The following is code, but I don't know how to get the line-breaks right.) ``` lang-cs const double Epsilon = 1e-15; const double RelErr = Epsilon * precisionLoss; bool isInteger = Math.Abs(Math.Round(x) - x) <= RelErr*scale; ``` – Jan Heldal Feb 04 '21 at 22:11
26

If you want to check for an Integer, this will do it:

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

If you additionally want to check if the number could be converted into an Int32:

public bool IsInt32(double number)
{
    return (number % 1 == 0) && number >= Int32.MinValue && number <= Int32.MaxValue;
}
Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
  • 3
    this won't work in cases of large double values, value range of double is larger than that of int. TryParse will give you false because of range but your mod will return true. Try it out with double.MaxValue – BrokenGlass Nov 02 '10 at 11:53
  • @BrokenGlass, @Tim: The question says "integer", not "int" or "Int32". Tim's original logic was correct in that it matched what the OP attempts in the question, returning true for any integer `double`, otherwise false. (Ideally the OP should clarify whether they mean `Int32` or just integer.) – LukeH Nov 02 '10 at 12:07
  • @LukeH: It fails with any integer datatype provided by C# though, even Int64 doesn't provide the same range as double. So you are correct in saying it is a valid integer check, but then what use is that to me practically if I can't store it in any integer variable? – BrokenGlass Nov 02 '10 at 12:11
  • @BrokenGlass: Does the OP say that they want to store it in an integer variable? Perhaps they just want to know whether or not it's an integer. That's what the question says. (As I said, ideally the OP should clarify what they really mean.) – LukeH Nov 02 '10 at 12:15
  • Ok that's fair, in that case I stand corrected. – BrokenGlass Nov 02 '10 at 12:17
17

The pitfall of working with string representations is the locale used and yoou have to take care of rounding issues. 0.999999999 can be considered to be integer 1 in most cases. Here is a small snippet taking into account rounding errors:

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

where EPSILON is a double value that is small enough for your purpose 0.00001 for example

See also this for some more information: http://msdn.microsoft.com/en-us/library/system.double.epsilon.aspx

jdehaan
  • 19,700
  • 6
  • 57
  • 97
6

Try:

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

Or the prettier:

public bool CheckIfInteger(double number)
{
    return (Math.Floor(number) == number);
}
Frédéric Hamidi
  • 258,201
  • 41
  • 486
  • 479
4

I'd use TryParse:

  double value = 2.0;
  int number;
  bool result = Int32.TryParse(value.ToString(), out number);
BrokenGlass
  • 158,293
  • 28
  • 286
  • 335
2
    public static bool CheckIfInteger(double number)
    {
        return number - Math.Truncate(number) == 0;
    }
QrystaL
  • 4,886
  • 2
  • 24
  • 28
2

I think that a better question is: How can I tell if a double is close enough to an integer to be considered an integer for my purposes? Because otherwise, you are bound to run into ambiguities. So I'd recommend something like this:

return Math.Abs(someDouble - Math.Round(someDouble)) < TOLERANCE;
o. nate
  • 384
  • 1
  • 3
1

I'm liking abatishchev's idea to use CurrentCulture.

return number.ToString().Contains(CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator) == false;

Would this not solve the epsilon problem (which I didn't even consider initially)?

Simon
  • 1,499
  • 3
  • 17
  • 23
0

I use the following string extension method which checks against a RegEx pattern

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