测试浮点数是否为整数

时间:2008-09-26 22:00:39

标签: c# floating-point numerical

此代码有效(C#3)

double d;
if(d == (double)(int)d) ...;
  1. 有更好的方法吗?
  2. 由于无关紧要的原因,我想避免双重演员;除此之外还有什么好方法? (即使它们不那么好)
  3. 注意:有几个人指出(重要的)点= =经常有问题重新浮点数。在这种情况下,我期望值在0到几百的范围内,它们应该是整数(非整数是错误),所以如果这些点“不应该”对我来说是一个问题。

12 个答案:

答案 0 :(得分:27)

d == Math.Floor(d)
换句话说,

做同样的事情。

NB:希望你知道做这种事情时你必须非常小心;浮点/双打很容易积累微小的错误,使得精确的比较(如本例)失败没有明显的原因。

答案 1 :(得分:5)

如果你的双倍是另一次计算的结果,你可能想要这样的东西:

d == Math.Floor(d + 0.00001);

这样,如果出现轻微的舍入错误,它仍会匹配。

答案 2 :(得分:5)

我认为这可行:

if (d % 1 == 0) {
  //...
}

答案 3 :(得分:5)

我无法回答问题的C#特定部分,但我必须指出你可能错过了浮点数的一般问题。

通常,在浮点数上没有很好地定义整数。出于同样的原因,在浮点数上没有很好地定义相等性。浮点计算通常包括舍入和表示错误。

例如,1.1 + 0.6 != 1.7

是的,这就是浮点数的工作方式。

此处1.1 + 0.6 - 1.7 == 2.2204460492503131e-16

严格来说,与浮点数相比,最接近相等比较的是将与选择的精度进行比较

如果这还不够,则必须使用十进制数表示,带有内置误差范围的浮点数表示,或者使用符号计算。

答案 4 :(得分:3)

如果你要转换它,Mike F / Khoth的答案很好,但并没有完全回答你的问题。如果您要进行实际测试,并且实际上非常重要,我建议您实施一些包含误差的内容。

例如,如果你正在考虑金钱并且想要测试甚至是美元金额,你可能会说(按照Khoth的模式):

if( Math.abs(d - Math.Floor(d + 0.001)) < 0.001)

换句话说,取值的差值的绝对值和它的整数表示,并确保它很小。

答案 5 :(得分:2)

你不需要额外的(双)。这有效:

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

答案 6 :(得分:2)

使用Math.Truncate()

答案 7 :(得分:2)

对于任何固定精度的FP编号,在数学上确保一个简单的测试,例如'x == floor(x)'可以正常工作。

所有合法的固定精度FP编码都代表不同的实数,因此对于每个整数x,最多只有一个固定精度FP编码与其完全匹配。

因此,对于以这种方式表示的每个整数x,我们必须有x == floor(x),因为floor(x)按定义返回最大的FP数y,使得y <= x和y代表一个整数;所以floor(x)必须返回x。

答案 8 :(得分:1)

这将允许您选择要查找的精度,加上或减去半个刻度,以解释浮点漂移。比较也是不可或缺的,这很好。

static void Main(string[] args)
{
    const int precision = 10000;

    foreach (var d in new[] { 2, 2.9, 2.001, 1.999, 1.99999999, 2.00000001 })
    {
        if ((int) (d*precision + .5)%precision == 0)
        {
            Console.WriteLine("{0} is an int", d);
        }
    }
}

,输出

2 is an int
1.99999999 is an int
2.00000001 is an int

答案 9 :(得分:0)

像这样的东西

double d = 4.0;
int i = 4;

bool equal = d.CompareTo(i) == 0; // true

答案 10 :(得分:0)

你能用这个

吗?
    bool IsInt(double x)
    {
        try
        {
            int y = Int16.Parse(x.ToString());
            return true;
        }
        catch 
        {
            return false;
        }
    }

答案 11 :(得分:0)

要处理双精度......

Math.Abs(d - Math.Floor(d)) <= double.Epsilon

考虑以下情况,其中小于double.Epsilon 的值无法比较为零。

// number of possible rounds
const int rounds = 1;

// precision causes rounding up to double.Epsilon
double d = double.Epsilon*.75;

// due to the rounding this comparison fails
Console.WriteLine(d == Math.Floor(d));

// this comparison succeeds by accounting for the rounding
Console.WriteLine(Math.Abs(d - Math.Floor(d)) <= rounds*double.Epsilon);

// The difference is double.Epsilon, 4.940656458412465E-324
Console.WriteLine(Math.Abs(d - Math.Floor(d)).ToString("E15"));