There are hacks to make it work, but the way that a double represents it's value means that it is quite possibly not storing an integer as you think it would. It may store 555 as 554.99999998 or something funny like that. There is no way to tell really, unless you have the original source values and figure it out from there. float and double are limited precision.
–
Ape-inagoOct 5 '09 at 18:30

3

@Ape-inago: Actually, a double which is assigned an integer value will actually equal that value. And adding, subtracting, and multiplying by integral-valued doubles also yields an integral-valued double. However, once you multiply by an arbitrary double or divide by a double, all bets are off.
–
rlbondOct 5 '09 at 18:51

What do you want d3 = 3.0 * (1.0 / 3.0) to return? Integer or not? As rlbond pointed out, multiplying by a non-integral double or dividing by anything is likely to result in something that may be extremely close to an integer, but may not be represented as a floating-point integer.
–
David ThornleyOct 5 '09 at 19:39

13 Answers
13

Edit: As Pete Kirkham points out, passing 0 as the second argument is not guaranteed by the standard to work, requiring the use of a dummy variable and, unfortunately, making the code a lot less elegant.

Integers (at least up to a certain size) are represented exactly in any real implementation of floating point numbers I can think of, so I don't think there's a need to worry about precision for this particular problem.
–
Laurence GonsalvesOct 5 '09 at 18:26

2

What about the case where d1 = 0.999999999999999 ?
–
AnnaOct 5 '09 at 18:26

1

The only problem is that floor goes the wrong way for negative numbers. you should use trunc()
–
Loki AstariOct 5 '09 at 18:35

1

@Jacob: You don't want to use the minimum value. You need a value that represents the accuracy you need for the application.
–
Loki AstariOct 5 '09 at 18:38

1

I must apologize. I was fixated on numbers that were exactly integers, not close to integer, and round is a better choice for the solution you provided.
–
Mark RansomOct 6 '09 at 2:36

modf returns the fractional part, so the test should be that the result of modf is 0.0.

modf takes two arguments, the second of which should be a pointer of the same type as the first argument. Passing NULL or 0 causes a segmentation fault in the g++ runtime. The standard does not specify that passing 0 is safe; it might be that it happens to work on avakar's machine but don't do it.

You could also use fmod(a,b) which calculates the a modulo b passing 1.0. This also should give the fractional part.

Now, it wouldn't be C if it didn't have about 40 years of language revisions...

In C, == returns int but in C++ it returns bool. At least on my Linux distro (Ubuntu) you need to either declare double trunc(double); or you could compile with -std=c99, or declare the level macro, all in order to get <math.h> to declare it.

Maybe make the return type bool, since this returns a boolean?
–
Daniel BinghamOct 5 '09 at 18:31

trunc() is better than floor(). It works for negative numbers.
–
Loki AstariOct 5 '09 at 18:36

Alcon, good point, it might be C++. Of course, in C, it isint. I've clarified things...
–
DigitalRossOct 5 '09 at 18:42

There is no trunc in C++ (except for ios::trunc).
–
avakarOct 5 '09 at 18:44

That's not exactly true, try it, at least with g++ it works. While 14882 does not specifically declare trunc, it does state, and I cite C++ 26.5 (2), The contents of these headers are the same as the Standard C library headers <math.h>, and conforming implementations of that are required to have trunc(). But yes, it might be safer to use floor().
–
DigitalRossOct 5 '09 at 19:21

Below you have the code for testing d1 and d2 keeping it very simple. The only thing you have to test is whether the variable value is equal to the same value converted to an int type. If this is not the case then it is not an integer.