0

I'm trying to check if a number of a double type is integer. In here, there are several methods. I've picked up one of them but the method is working just fine without a loop. Once I put it inside a loop, it works with some numbers and fails to check other. This is the code

#include <iostream>
#include <cmath>

bool IsInteger(double x) {
  return std::fmod(x, static_cast<decltype(x)>(1.0)) == 0.0;  // Test if fraction is 0.0.
}

int main(int argc, char* argv[])
{

    for (double i(0); i <= 4.0; i += 0.2 )
        if ( IsInteger(i) )
            std::cout << i << "   " << IsInteger(i) << std::endl;

    return 0;
}

The preceding code works with 0.0 and 1.0 but fails to verify 2.0 and 3.0. The code is running in Windows 7 and the compiler is the visual studio. I am Ok with boost if there is a function regarding this matter.

Community
  • 1
  • 1
CroCo
  • 5,531
  • 9
  • 56
  • 88
  • 2
    I bet that's because it's not 2.0 or 3.0. It's 1.99999999999999999999 or something like that. – user253751 Apr 28 '16 at 09:04
  • @immibis, why it worked with `1.0`? – CroCo Apr 28 '16 at 09:05
  • 2
    because that was (apparently) exactly 1.0, and not 0.9999999999 or 1.00000000001 – user253751 Apr 28 '16 at 09:06
  • `0.2` cannot be represented exactly in a double: `0x3fc999999999999a`. – Jongware Apr 28 '16 at 09:10
  • 2
    This is not directly to do with your integer test, it's because adding `0.2` to `1.0` five times has not resulted in exactly `2.0`. It's close enough that printing it with the default format displays `2`, but not exact. – Steve Jessop Apr 28 '16 at 09:10
  • 1
    ... a closer value on my machine, displayed by calling `std::cout.precision(60)` and then printing `i`, is `1.999999999999999777955395074968691915273666` – Steve Jessop Apr 28 '16 at 09:16
  • @SteveJessop, perfect but how can I overcome this problem? I'm implementing a controller for robot which its the input must be changed every second. – CroCo Apr 28 '16 at 09:18
  • 2
    @CroCo: unfortunately "controlling a robot" is too high-level and "testing whether `1.0 + 0.2 + 0.2 + 0.2 + 0.2 + 0.2` is an integer" is too low-level to provide an answer. There are two common strategies, one is to choose an amount of tolerance and test whether the value is within that distance of an integer. The other is to use a class that provides decimal arithmetic instead of `double`. In your case, perhaps you could dispense with the class and just use an `int` representing tenths-of-a-whatever. It depends on your requirements and on the rest of your code. – Steve Jessop Apr 28 '16 at 09:20
  • Cant you just use integers and check whether they are 0 when computed mod 5 (in your case with 0.2 step size)? You can multiply with 0.2 later if needed. 0.2 cannot be represented precisely in floating point, thats why your code fails. Also, using doubles in a loop counter is rarely a good idea. – masterxilo Apr 28 '16 at 10:47

0 Answers0