views:

190

answers:

6

I can think of several ways, eg.

Convert.ToInt32(floatingPoint) - floatingPoint == 0;
Math.Truncate(floatingPoint) - floatingPoint == 0;
floatingPoint % 1 == 0;
Math.Floor(floatingPoint) == floatingPoint;
//etc...

But which method is most reliable?

+1  A: 

Regardless of the reliability, the modulo method looks easy to understand (no need to read any specification) and fast (no function call).

+1  A: 

You will run into the classic problem of floating point numbers being only approximations. If you do this:

floatingPoint = 1.0/3.0;
floatingPoint *= 3;

you will end up with something close to, but not exactly, 1.

Ned Batchelder
+2  A: 

Floating points can't represent some integers exactly, so there is no method that is truly reliable. Specifically, any int that is greater than 2^24 cannot be represented exactly by a float. Alas, that is part of the price you pay for using a floating-point representation!

For an excellent summary of the various issues with floating point that you should be aware of, I encourage you to check out "What Every Computer Scientist Should Know About Floating-Point Arithmetic".

John Feminella
+5  A: 

You should not check for exact equality to zero, as a floating point number usually only contains the closest possible approximation to the number that you assigned to it.

For example, the closest possible value to 42 that the type could represent might be something like 42.00000000000000662, which you still would want to count as an integer value.

Take the difference between the value and the rounded value, then take the absolute value of that (so that it's not negative) and compare to a small value:

if (Math.Abs(Math.Round(floatingPoint) - floatingPoint) < 0.000001) ...
Guffa
Integers can be represented exactly in floating point notation. Your example of 42.00000000000000662 simply cannot happen.
Jimmy J
This isn't a good idea. Eventually the difference between consecutive bit floating-point representations will be larger than 0.5, and then it's not clear what integer the number is supposed to represent.
John Feminella
@Jimmy: That's not true. Try representing 2^31-1 exactly in a single-precision floating-point implementation.
John Feminella
+1  A: 

There is no generally reliable method.

Since floating point numbers are (mostly) always an approximation if they are the result of previous calculations, there is no simple integer equivalence, as others pointed out.

You have to consider range and precision of both fp and int values you're dealing with. It all depends of what you are trying to achieve.

Guffa has a good approach using an allowed range of precision for int comparison.

devio
A: 

Integers can be represented exactly in floating point representation so any of those should work if you're checking for an exact integer (personally I'd use the first one...)

Jimmy J