# Strange behavior with casting primitive types

Discussion in 'C++' started by Gaijinco, Mar 8, 2009.

1. ### GaijincoGuest

Why does this not work properly?

It's a way to know if how many decimal numbers have a double.

#include <iostream>
using namespace std;

int countDecimals(double d) {
int x = (int)d;
int decimals = 0;
while((x/d) != 1.0) {
d *= 10.0;
x = (int)d;
++decimals;
//cout << x/d << endl; getchar();
}
return decimals;
}

int main() {
cout << countDecimals(3.1415);
return 0;
}

In my computer the answer is OK with 3 or less decimal numbers, but
wrong for everything else!

Thanks!

Gaijinco, Mar 8, 2009

2. ### Alf P. SteinbachGuest

* Gaijinco:
With most C++ implementations a 'double' value is not represented as a decimal
number, so it simply doesn't have decimals.

The decimal specification '3.1415' means the double value that is closest to
decimal 3.1415.

It's more or less a coincidence that it seems to work the way you thought it
should work, since with a typical C++ implementation you don't have decimal
digits in there.

Cheers & hth.,

- Alf

Alf P. Steinbach, Mar 8, 2009

3. ### Marcel MüllerGuest

In general the above condition is always true since an approximate
number will never be exactly equal to something special, because it is
an /approximate/ number. You can be lucky that int has more significant
bits than double on your platform. Otherwise you might get a floating
point exception, because the loop never terminates.

Do never equality compare approximate numbers to something else but zero!

Of course, on most platforms integral numbers can be represented exactly
as approximate numbers as long as they are not too large. But one should
not rely on that. In case you can guarantee that, you also could have
choosen an integral data type.

Most likely other numbers like 0,3125 are exact too. The reason is
simply that their reduced rational representation has nothing but the
prime factor two in the denominator.

Marcel

Marcel Müller, Mar 8, 2009
4. ### James KanzeGuest

Where do you see any approximate numbers in this code? 1.0 is
exactly representable in every floating point format I know of.

Alf explained the problem correctly, IMHO. I'm not sure what he
really means by "decimal numbers having a double", but since he
doesn't have any decimal numbers in his program, it's really
irrelevant.
Or that he simply didn't try any integer values that couldn't be
represented exactly in a double.
Don't do any comparisons until you know what you're doing. You
can get in trouble just as quickly with comparisons for
inequality.
It depends. On a lot of platforms, the largest integral type
has (or had) 32 bits. An IEEE double can represent all of the
integers up to 2^52 exactly, however, and I've seen it used
simply for the greater range.

James Kanze, Mar 8, 2009
5. ### Juha NieminenGuest

'd' can be (and often is) an approximation because there's no 1-to-1
mapping between base-10 floating point values (which is what you write
in your C++ source code) and base-2 floating point values, which is what
most systems use internally. Thus when you give a value of the former
type to that function, the compiler will convert it (at compile time)
internally to a value of the latter type, and these two values may not
be equal, hence 'd' may be just an approximation of the original value
in the source code.

Hence x/d and d*10.0 will also be approximations.

Juha Nieminen, Mar 8, 2009
6. ### James KanzeGuest

Any actual value is exact in itself, but can be an approximation
of some other value outside the system. (In physical systems,
this is always the case, independantly of the representation;
all measurements are inprecise to a certain degree.)

I'm not too sure what the original poster is trying to do. He
said something about whether a "decimal" has a double, which
sounds to me whether, given a decimal x, the value 2*x exists.
Which, of course, doesn't make sense. But as Alf said, using
floating point to evaluate "decimal" characteristics just isn't
going to work---comparison for equality or not. Floating point
doesn't have the characteristics of a decimal, and is not a good
abstraction for the set of "decimal" numbers (whatever that
means---I've always understood decimal as refering to a
representation, and not a set of numbers).
But what is the original value. In the funtion above, the
original value *is* d.
Approximations of what? Saying that something is an
approximation supposes that there is an exact value which is
being approximated. In the function, the only "exact values" I
can see are 1.0 and 10.0, both of which are exactly
representable in all of the floating point formats I know.

Of course, the original poster doubtlessly had something in
mind, and d (and the other calculated values) are likely just
approximations of that something. But until he tells us what,
we can only guess.

(It just occurs to me that what he's asking might be simply
whether a given decimal has an exact representation as a double.
In which case, the solution is to convert it, and see if you
need to round the final results. In other words, you have to
work with the original decimal format.)

James Kanze, Mar 9, 2009