Test if a floating point number is an integer

前端 未结 12 2369
醉酒成梦
醉酒成梦 2021-02-18 22:21

This code works (C# 3)

double d;
if(d == (double)(int)d) ...;
  1. Is there a better way to do this?
  2. For extraneous reasons I want to
相关标签:
12条回答
  • 2021-02-18 22:30

    I cannot answer the C#-specific part of the question, but I must point out you are probably missing a generic problem with floating point numbers.

    Generally, integerness is not well defined on floats. For the same reason that equality is not well defined on floats. Floating point calculations normally include both rounding and representation errors.

    For example, 1.1 + 0.6 != 1.7.

    Yup, that's just the way floating point numbers work.

    Here, 1.1 + 0.6 - 1.7 == 2.2204460492503131e-16.

    Strictly speaking, the closest thing to equality comparison you can do with floats is comparing them up to a chosen precision.

    If this is not sufficient, you must work with a decimal number representation, with a floating point number representation with built-in error range, or with symbolic computations.

    0 讨论(0)
  • 2021-02-18 22:32

    You don't need the extra (double) in there. This works:

    if (d == (int)d) {
     //...
    }
    
    0 讨论(0)
  • 2021-02-18 22:37

    If you are just going to convert it, Mike F / Khoth's answer is good, but doesn't quite answer your question. If you are going to actually test, and it's actually important, I recommend you implement something that includes a margin of error.

    For instance, if you are considering money and you want to test for even dollar amounts, you might say (following Khoth's pattern):

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

    In other words, take the absolute value of the difference of the value and it's integer representation and ensure that it's small.

    0 讨论(0)
  • 2021-02-18 22:47
    d == Math.Floor(d)
    

    does the same thing in other words.

    NB: Hopefully you're aware that you have to be very careful when doing this kind of thing; floats/doubles will very easily accumulate miniscule errors that make exact comparisons (like this one) fail for no obvious reason.

    0 讨论(0)
  • 2021-02-18 22:47

    Could you use this

        bool IsInt(double x)
        {
            try
            {
                int y = Int16.Parse(x.ToString());
                return true;
            }
            catch 
            {
                return false;
            }
        }
    
    0 讨论(0)
  • 2021-02-18 22:49

    To handle the precision of the double...

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

    Consider the following case where a value less then double.Epsilon fails to compare as zero.

    // 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"));
    
    0 讨论(0)
提交回复
热议问题