How to determine if a decimal/double is an integer?
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 outpu开发者_如何学运维t the value using .ToString("N0")
or .ToString("N2")
. If there is no decimal point value, then I don't want to show that.
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)
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;
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);
}
bool IsInteger(double num) {
if (ceil(num) == num && floor(num) == num)
return true;
else
return false;
}
Problemo solvo.
Edit: Pwned by Mark Rushakoff.
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
static bool IsWholeNumber(double x)
{
return Math.Abs(x % 1) < double.Epsilon;
}
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 ;
If upper and lower bound of Int32
matters:
public bool IsInt32(double value)
{
return value >= int.MinValue && value <= int.MaxValue && value == (int)value;
}
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.
.NET 7 now has built-in methods for this:
decimal.IsInteger
: https://learn.microsoft.com/en-us/dotnet/api/system.decimal.isinteger?view=net-7.0double.IsInteger
: https://learn.microsoft.com/en-us/dotnet/api/system.double.isinteger?view=net-7.0
You can check out the source code at:
- https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Decimal.cs
- https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Double.cs
public static bool isInteger(decimal n)
{
return n - (Int64)n == 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.
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();
You can simply compare the double against the int cast of the same value.
double d = 5.0m;
if (d == (int)d)
{
....
}
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;
}
Try this:
number == Convert.ToInt16(number);
Perhaps not the most elegant solution but it works if you are not too picky!
bool IsInteger(double num) {
return !num.ToString("0.################").Contains(".");
}
精彩评论