Strange behavior with casting primitive types

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

  1. Gaijinco

    Gaijinco Guest

    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
    #1
    1. Advertisements

  2. * 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
    #2
    1. Advertisements

  3. 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
    #3
  4. Gaijinco

    James Kanze Guest

    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
    #4
  5. '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
    #5
  6. Gaijinco

    James Kanze Guest

    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
    #6
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.