309

How do I tell if a decimal or double value is an integer?

For example:

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

or

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

The reason I would like to know this is so that I can determine programmatically if I want to output the value using .ToString("N0") or .ToString("N2"). If there is no decimal point value, then I don't want to show that.

1
  • Math.Floor(float.Parse(inputValue)) == float.Parse(inputValue) Commented Dec 28, 2021 at 12:34

18 Answers 18

558

For floating point numbers, n % 1 == 0 is typically the way to check if there is anything past the decimal point.

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

Output:

False
True

Update: As @Adrian Lopez mentioned below, comparison with a small value epsilon will discard floating-point computation mis-calculations. Since the question is about double values, below will be a more floating-point calculation proof answer:

Math.Abs(d % 1) <= (Double.Epsilon * 100)
Sign up to request clarification or add additional context in comments.

15 Comments

That works when the number starts out as a whole number, but not necessarily when the number is the result of some floating-point computation. How about something like "(d % 1) < epsilon" where epsion is some small value?
It's a shame that the best answer in this thread is a comment, rather than the accepted answer. Nice one Adrian.
I also think Adrian's comment above is the best answer. To put his advice in formal C# code: if (Math.Abs(n % 1) < Double.Epsilon) {// Do something if n is integer}.
Actually, as the question is stated, this answer is correct and the comments are wrong. The OP doesn't want to know whether a double is an integer for mathematical purposes, but rather how to display it. Only exact integer values should be displayed without a decimal point. Also, the comment about about mod not being useful with floating point and not working outside of .NET is not well informed. And (int)d is a disaster that will throw an exception for most double values.
double.Epsilon * 100 is also not suitable. A proper epsilon value needs to be scaled to the values being compared. The smallest possible change in a double is a fraction of the value, not a fixed amount. The value they chose for C# double.Epsilon is also particularly bad because they used a different concept than DBL_EPSILON in C that's been around for decades and is actually useful.
|
60

There are any number of ways to do this. For example:

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

You can also use modulo.

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

11 Comments

Would one of these be faster than the other? I'm wanting to do this in a performance sensitive context.
@Basil - Depends on the circumstances. You should do some timings for yourself and judge.
Math.Abs(d-(int)d) < double.Epsilon is safer than d == (int)d
@MathewFoscarini - I think you're confused. It sets it to false, because the result of 16.1 - 6.1 is not an int. The point was to find if a given value is an int, not if something that is approximately an int is an int.
@MathewFoscarini - Yes, an int is a number without a decimal value (or a decimal value of 0). 16.1-6.1 does not create a 0 decimal value, it's a very small non-zero value that is caused by IEEE Floating Point format quirks. There is no way to know whether the number is SUPPOSED to have a decimal value or not, so assuming a rounding value is just as inaccurate. The purpose of the question was to know whether a floating point number was an integer, not whether it was approximately an integer.
|
28

How about this?

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

Same code for decimal.

Mark Byers made a good point, actually: this may not be what you really want. If what you really care about is whether a number rounded to the nearest two decimal places is an integer, you could do this instead:

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

1 Comment

perhaps update your solution and add: && number<int.MaxValue && number>int.MinValue
21

.NET 7 now has built-in methods for this:

You can check out the source code at:

Comments

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

Problemo solvo.

Edit: Pwned by Mark Rushakoff.

2 Comments

or just return ceil(num) == num && floor(num) == num;
or just return ceil(num) == floor(num);
13

Whilst the solutions proposed appear to work for simple examples, doing this in general is a bad idea. A number might not be exactly an integer but when you try to format it, it's close enough to an integer that you get 1.000000. This can happen if you do a calculation that in theory should give exactly 1, but in practice gives a number very close to but not exactly equal to one due to rounding errors.

Instead, format it first and if your string ends in a period followed by zeros then strip them. There are also some formats that you can use that strip trailing zeros automatically. This might be good enough for your purpose.

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

Output:

1
1.02

7 Comments

@Mark Sounds interesting. Do you have an example of a format that strips trailing zeros?
I agree that it is safer and what the OP should probably do, but it is not an answer to the narrower (but more interesting) question of whether a value has a fractional part or not.
@Clifford: I usually try to answer based on what is best to solve the OPs problem, not based on what the title says. Titles are rarely an accurate description of the problem.
+1 Agree that trying to test floats or doubles to see if they could be ints is bad due to rounding and precision errors.
For money usage, you would probably want 1.2 to be displayed as 1.20, which is not the case with the suggested solution. Any takers?
|
6
static bool IsWholeNumber(double x) 
{
    return Math.Abs(x % 1) < double.Epsilon;
}

1 Comment

The answer will not work for double x = 0.31d + 0.27d - 0.58d;
4

Mark Rushakoff's answer may be simpler, but the following also work and may be more efficient since there is no implicit division operation:

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

and

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

If you want a single expression for both types, perhaps

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

Comments

3

If upper and lower bound of Int32 matters:

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

2 Comments

First test, then cast like this it would throw an exception other than return false, perhaps update your answer
@computer, yes good point. Regarding throwing on cast, I guess it would depend on your project setting.
2

You can use String formatting for the double type. Here is an example:

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"

Let me know if this doesn't help.

2 Comments

That does not really address the question of determining if a value has no fractional part, which is a mathematical question. It is however probably what the OP needs given his explanatory note.
Yes, he want just to format double or decimal value without decimal point. Thank you...
2
    public static bool isInteger(decimal n)
    {
        return n - (Int64)n == 0;
    }

1 Comment

What's the difference from this answer?
0

I faced a similar situation, but where the value is a string. The user types in a value that's supposed to be a dollar amount, so I want to validate that it's numeric and has at most two decimal places.

Here's my code to return true if the string "s" represents a numeric with at most two decimal places, and false otherwise. It avoids any problems that would result from the imprecision of floating-point values.

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

I discuss this in more detail at http://progblog10.blogspot.com/2011/04/determining-whether-numeric-value-has.html.

1 Comment

This assumes that you're working with one culture. For example, It would not work properly with cultures that represent decimals like 1.000,00
0

Using int.TryParse will yield these results:

        var shouldBeInt = 3;

        var shouldntBeInt = 3.1415;

        var iDontWantThisToBeInt = 3.000f;

        Console.WriteLine(int.TryParse(shouldBeInt.ToString(), out int parser)); // true

        Console.WriteLine(int.TryParse(shouldntBeInt.ToString(), out parser)); // false

        Console.WriteLine(int.TryParse(iDontWantThisToBeInt.ToString(), out parser)); // true, even if I don't want this to be int

        Console.WriteLine(int.TryParse("3.1415", out  parser)); // false

        Console.WriteLine(int.TryParse("3.0000", out parser)); // false

        Console.WriteLine(int.TryParse("3", out parser)); // true

        Console.ReadKey();

Comments

0

You can simply compare the double against the int cast of the same value.

double d = 5.0m;

if (d == (int)d)
{
.... 
}

Comments

0

This is my solution to this problem. Maybe someone will useful.

public static bool IsInt(object number, int? decimalPlaces = null)
{
    bool isInt;
    var splinted = number.ToString().Split(',');

    if (splinted.Length == 1)
        isInt = true;
    else
    {
        var charsAfterComma = decimalPlaces != null ? splinted[1].Substring(0, (int) decimalPlaces) : splinted[1];  
        isInt = charsAfterComma.First().ToString() == "0" && charsAfterComma.Replace("0", "") == "";
    }

    return isInt;
}

1 Comment

Have you considered other cultures because this would not work with cultures that uses , for decimal separator.
0

The best way is to use the built-in static method rather than any of the other answers:

double.IsInteger(4.5) // false

1 Comment

This does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From Review
-2

Try this:

number == Convert.ToInt16(number);

Comments

-4

Perhaps not the most elegant solution but it works if you are not too picky!

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

1 Comment

This is a terrible solution

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.