如何确定小数/双精度数是否为整数?


225

如何判断小数或双精度值是整数?

例如:

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")。如果没有小数点值,那么我不想显示出来。

Answers:


410

对于浮点数,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 Lopez所述,与较小的值进行比较epsilon将丢弃浮点计算错误的计算。由于问题是关于double值的,因此下面是一个更浮点计算证明的答案:

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

96
当数字以整数开头时有效,但当数字是某些浮点计算的结果时不一定有效。比如“(d%1)<epsilon”,epsion值很小吗?
阿德里安·洛佩兹

9
可惜的是,这个线程中最好的答案是评论,而不是公认的答案。不错的一位阿德里安。
starkythehutch

13
我也认为上述Adrian的评论是最好的答案。将他的建议用正式的C#代码表示:if(Math.Abs​​(n%1)<Double.Epsilon){//如果n为整数,则执行某些操作。
鲁宾·拉米雷斯·帕德隆

7
恕我直言,模数运算符和浮点数只是没有以任何有用的方式混合。考虑到所使用的击键次数,建议的代码令人难以置信,并且在.NET语言之外几乎无法使用。我敢打赌,它也比正确的方法慢得多(正确的方法根本不使用任何除法)。正确的方法是使用Math.Abs(d-(int)d) < double.Epsilon。就像我们应该在大学上的第一门编程课的第一周就学到了一样。
krowe2

9
实际上,正如问题所指出的,此答案是正确的,而注释是错误的。OP不想知道双精度数是否是用于数学目的的整数,而是想知道如何显示它。仅应显示不带小数点的精确整数值。另外,关于mod不能用于浮点并且不能在.NET之外运行的评论也不是很清楚。这(int)d是一场灾难,将为大多数double值引发异常。
Jim Balter

49

有许多方法可以做到这一点。例如:

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

您也可以使用模。

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

其中一个会比另一个快吗?我想在对性能敏感的环境中执行此操作。
罗勒

@Basil-视情况而定。您应该为自己做一些计时并做出判断。
Erik Funkenbusch 2013年

4
Math.Abs(d-(int)d) < double.Epsilond == (int)d
Reactgular 2014年

3
@MathewFoscarini-我认为你很困惑。它将其设置为false,因为16.1-6.1的结果不是整数。关键是要确定给定值是否为整数,而不是近似值的东西是否为整数。
Erik Funkenbusch 2014年

1
@MathewFoscarini-是的,int是一个没有十进制值(或十进制值0)的数字。16.1-6.1不会创建十进制值0,它是由IEEE浮点格式的怪癖引起的非常小的非零值。无法知道该数字是否应为十进制值,因此假设舍入值同样不准确。这个问题的目的是要知道浮点数是否是整数,而不是浮点数是否近似于整数。
Erik Funkenbusch 2014年

21

这个怎么样?

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

的相同代码decimal

实际上,马克·拜尔斯(Mark Byers)提出了一个好观点:这可能并不是您真正想要的。如果您真正关心的是四舍五入到小数点后两位的数字是否是整数,则可以执行以下操作:

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

1
也许更新您的解决方案并添加:&& number <int.MaxValue && number> int.MinValue
Walter Vehoeven

12

尽管所提出的解决方案似乎适用于简单的示例,但通常这样做不是一个好主意。一个数字可能不完全是整数,但是当您尝试对其进行格式设置时,它足够接近您所获得的整数1.000000。如果您进行了计算,理论上应该给出正好为1,但实际上由于舍入误差而得出的数字非常接近但不等于1,那么就会发生这种情况。

相反,请先对其进行格式化,如果您的字符串以句点结束,后跟零,则将其剥离。您还可以使用某些格式来自动去除尾随零。这可能足以满足您的目的。

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

输出:

1
1.02

@Mark听起来很有趣。您是否有去除尾随零的格式示例?
Jim Geurts'5

我同意这是更安全的,OP应该怎么做,但这并不是对一个更狭窄(但更有趣)的问题的答案,即值是否具有小数部分。
克利福德,2010年

3
@Clifford:我通常会尝试根据最能解决OP问题的答案来回答问题,而不是根据标题中的回答。标题很少是问题的准确描述。
Mark Byers

+1同意由于舍入和精度错误,尝试测试浮点数或双精度数以查看它们是否可能是整数是不好的。
罗曼·希波

1
对于资金使用,您可能希望将1.2显示为1.20,建议的解决方案不是这种情况。有参加者吗?
Kjell Rilbe

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

问题解决。

编辑:马克·鲁沙科夫(Mark Rushakoff)拥有。


4
或者只是return ceil(num) == num && floor(num) == num;
布赖恩·拉斯穆森

13
或只是return ceil(num) == floor(num);
gregsdennis 2013年

4

Mark Rushakoff的答案可能更简单,但由于没有隐式除法运算,以下内容也可以工作并且可能更有效:

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

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

如果您想为这两种类型使用单个表达式,也许

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

4

如果事上下限Int32

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

第一次测试,然后像这样进行转换,它会引发除返回false以外的异常,也许会更新您的答案
Walter Vehoeven

@计算机,是的。关于投射,我想这取决于您的项目设置。
nawfal

3
static bool IsWholeNumber(double x) 
{
    return Math.Abs(x % 1) < double.Epsilon;
}

2

您可以将字符串格式用于double类型。这是一个例子:

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
那实际上并没有解决确定一个值是否没有小数部分的问题,这是一个数学问题。但是,OP可能会给出他的解释性注释。
克利福德,2010年

2
是的,他只想格式化双精度或十进制值而没有小数点。谢谢...
BALKANGraph 2010年


0

我遇到了类似的情况,但其中的值是字符串。用户键入的值应该是美元金额,因此我想验证其为数字并且最多具有两个小数位。

这是我的代码,如果字符串“ s”表示一个数字(最多两个小数位),则返回true,否则返回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
Jim Geurts

0

使用int.TryParse将产生以下结果:

        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();

-2

也许不是最优雅的解决方案,但是如果您不太挑剔的话,它会起作用!

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

8
这是一个糟糕的解决方案
Ospho

-2

您可以使用“ TryParse”方法。

int.TryParse()

这将检查该值是否可以转换为整数整数值。然后,结果可以指示一个标志,该标志可以在代码的其他地方使用。


int.TryParse的参数是字符串,而不是双精度型。
Jim Balter

yourDouble.toString("G17")
BackDoorNoBaby

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.