如何确定十进制/双精度是否为整数?

Jim*_*rts 210 c#

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

例如:

decimal d = 5.0; // Would be true
decimal f = 5.5; // Would be false
Run Code Online (Sandbox Code Playgroud)

要么

double d = 5.0; // Would be true
double f = 5.5; // Would be false
Run Code Online (Sandbox Code Playgroud)

我想知道这个的原因是我可以通过编程方式确定是否要使用.ToString("N0")或输出值.ToString("N2").如果没有小数点值,那么我不想显示.

Mar*_*off 385

对于浮点数,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);
}
Run Code Online (Sandbox Code Playgroud)

输出:

False
True
Run Code Online (Sandbox Code Playgroud)

更新:正如下面提到的@Adrian Lopez,与较小值的比较epsilon将丢弃浮点计算错误计算.由于问题是关于double值,下面将是一个更浮点计算证明答案:

Math.Abs(d % 1) <= (Double.Epsilon * 100)
Run Code Online (Sandbox Code Playgroud)

  • 当数字作为整数开始时,这种方法有效,但不一定是数字是某些浮点计算的结果.像"(d%1)<epsilon"这样的东西,其中epsion是一个小值? (93认同)
  • 我也认为阿德里安的评论是最好的答案.将他的建议放在正式的C#代码中:if(Math.Abs​​(n%1)<Double.Epsilon){//如果n是整数则做一些事情}. (13认同)
  • 令人遗憾的是,这个帖子中的最佳答案是评论,而不是接受的答案.好一个阿德里安. (9认同)
  • 实际上,正如问题所述,这个答案是正确的,评论是错误的.OP不想知道double是否是用于数学目的的整数,而是如何显示它.只显示*exact*整数值而不显示小数点.另外,关于mod对浮点不起作用而不在.NET之外工作的评论并不充分.并且`(int)d`是一种灾难,会为大多数双值抛出异常. (7认同)
  • 恕我直言,模数运算符和浮点数不会以任何有用的方式混合.考虑到使用的击键次数,建议的代码令人难以置信地混淆,并且在.NET语言之外几乎无处可用.我敢打赌,它也比正确的方式慢得多(根本不使用任何分区).正确的方法是使用`Math.Abs​​(d-(int)d)<double.Epsilon`.就像我们应该在大学第一个编程课的第一周学到的一样. (6认同)
  • double.Epsilon * 100 也不适合。需要将适当的 epsilon 值缩放到要比较的值。double 中可能的最小变化是值的一小部分,而不是固定数量。他们为 C# double.Epsilon 选择的值也特别糟糕,因为他们使用的概念与 C 中的 DBL_EPSILON 不同,后者已经存在了几十年并且实际上很有用。 (3认同)

Eri*_*sch 44

有很多方法可以做到这一点.例如:

double d = 5.0;
bool isInt = d == (int)d;
Run Code Online (Sandbox Code Playgroud)

你也可以使用modulo.

double d = 5.0;
bool isInt = d % 1 == 0;
Run Code Online (Sandbox Code Playgroud)

  • `Math.Abs​​(d-(int)d)<double.Epsilon`比`d ==(int)d更安全 (4认同)
  • @MathewFoscarini - 我觉得你很困惑.它将其设置为false,因为16.1 - 6.1的结果不是int.关键是要找出给定值是否为int,而不是大约是int的东西是int. (3认同)
  • @MathewFoscarini - 是的,int 是一个没有十进制值(或十进制值为 0)的数字。16.1-6.1 不会创建 0 十进制值,它是由 IEEE 浮点格式怪癖引起的非常小的非零值。无法知道数字是否应该具有十进制值,因此假设四舍五入值同样不准确。这个问题的目的是要知道一个浮点数是否是一个整数,而不是它是否近似于一个整数。 (2认同)

Dan*_*Tao 17

这个怎么样?

public static bool IsInteger(double number) {
    return number == Math.Truncate(number);
}
Run Code Online (Sandbox Code Playgroud)

相同的代码decimal.

马克拜尔斯提出了一个很好的观点,实际上:这可能不是你真正想要的.如果您真正关心的是舍入到最接近的两位小数的数字是否为整数,则可以这样做:

public static bool IsNearlyInteger(double number) {
    return Math.Round(number, 2) == Math.Round(number);
}
Run Code Online (Sandbox Code Playgroud)


Mar*_*ers 12

虽然提出的解决方案似乎适用于简单的示例,但总的来说这样做是个坏主意.一个数字可能不是一个整数,但是当你尝试格式化它时,它足够接近你得到的整数1.000000.如果你做一个理论上应该给出1的计算,但实际上由于舍入误差而给出一个非常接近但不完全等于1的数字,就会发生这种情况.

相反,首先对其进行格式化,如果您的字符串以句点结尾,后跟零,则将其删除.您还可以使用一些格式自动删除尾随零.这可能足以满足您的目的.

double d = 1.0002;
Console.WriteLine(d.ToString("0.##"));
d = 1.02;
Console.WriteLine(d.ToString("0.##"));
Run Code Online (Sandbox Code Playgroud)

输出:

1
1.02
Run Code Online (Sandbox Code Playgroud)

  • @Clifford:我通常会根据什么是最好的解决OP问题来回答,而不是基于标题所说的.标题很少是对问题的准确描述. (3认同)

Pup*_*ppy 10

bool IsInteger(double num) {
    if (ceil(num) == num && floor(num) == num)
        return true;
    else
        return false;
}
Run Code Online (Sandbox Code Playgroud)

问题解决方案.

编辑:由Mark Rushakoff担任.

  • 或者只是`return ceil(num)== floor(num);` (13认同)
  • 或者只是`return ceil(num)== num && floor(num)== num;` (4认同)

pom*_*ber 5

static bool IsWholeNumber(double x) 
{
    return Math.Abs(x % 1) < double.Epsilon;
}
Run Code Online (Sandbox Code Playgroud)

  • 答案不适用于“double x = 0.31d + 0.27d - 0.58d;” (2认同)