static_cast<unsigned int> question...

Discussion in 'C++' started by GuineaPig, Nov 14, 2003.

  1. GuineaPig

    GuineaPig Guest

    Hello,

    I'm (very) new to c++ and I'm having trouble understanding why this doesn't
    work. Here's some testcode:

    #include <iostream.h>

    int main()
    {
    float test;
    unsigned int test2;
    test = 1.8;
    cout << "\n" << test*100.0 << endl;
    test2 = static_cast<unsigned int>(test*100.0);
    cout << "\n" << test2 << endl;

    }


    The strange thing is that the program returns 180 on the first cout (as
    expected) but it returns 179 on the second ???
    If I make test 1.7, I get 170 on the first and second cout ???
    I tried a whole bunch of other values... Sometimes I'm getting what I
    expected, sometimes not...

    Can anyone explain this to me ?

    Tnx in advance,

    Tom
     
    GuineaPig, Nov 14, 2003
    #1
    1. Advertising

  2. GuineaPig

    Fraser Ross Guest

    Its nothing to do with static_cast and it is not needed.

    test2 = static_cast<unsigned int>(test*100.0);


    Probably your processor only does 64 bit floating point. float is 32bit.
    The float of 1.8 is converted to a double of something like 1.7999999513.

    The standard says:
    The values of the floating operands and the results of floating
    expressions may be represented in greater precision and range than
    that required by the type; the types are not changed thereby

    The truncation to unsinged int made the loss of precision.

    Fraser.
     
    Fraser Ross, Nov 14, 2003
    #2
    1. Advertising

  3. GuineaPig wrote:
    >
    > Hello,
    >
    > I'm (very) new to c++ and I'm having trouble understanding why this doesn't
    > work. Here's some testcode:
    >
    > #include <iostream.h>
    >
    > int main()
    > {
    > float test;
    > unsigned int test2;
    > test = 1.8;
    > cout << "\n" << test*100.0 << endl;
    > test2 = static_cast<unsigned int>(test*100.0);
    > cout << "\n" << test2 << endl;
    >
    > }
    >
    > The strange thing is that the program returns 180 on the first cout (as
    > expected) but it returns 179 on the second ???


    That's because you computer cannot store the value 1.8 exactly.
    It may be stored as 1.7999999999999999... or 1.80000000000001 or
    something like that.

    Multiplying with 100 gives 179.9999999999999999... or
    180.0000000000001 or something like that.

    When operator<< outputs a floating point number, this number is
    rounded to x decimal digits (usually x equals 6, if nothing else specified).
    So rounding 179.99999999999999 to 6 digits yields (surprise) 180.000000
    Rounding 180.00000000000001 to six digits also yields 180.000000
    (and of course the superflous decimal digits are not output).

    Note: The number was *rounded* in order to be printed.

    The cast does a very different thing. The cast truncates the
    decimal digits from a number.

    179.9999999999999999 is close to 180.0, but that doesn't
    matter. Truncating the decimal digits still leaves you with
    179.

    180.0000000000000001 is also close to 180.0, but this time
    truncating the decimal digits leaves you with 180.

    The difference: rounding gives a different result then truncating.

    > If I make test 1.7, I get 170 on the first and second cout ???
    > I tried a whole bunch of other values... Sometimes I'm getting what I
    > expected, sometimes not...


    It depends on how the numbers are stored. Note: A computer cannot
    store every floating point number exactly. In the range 0 .. 1
    there are indefinitly many floating point numbers and your computer
    only has a finite memory.

    --
    Karl Heinz Buchegger
     
    Karl Heinz Buchegger, Nov 14, 2003
    #3
  4. > I'm (very) new to c++ and I'm having trouble understanding why this
    doesn't
    > work. Here's some testcode:
    >
    > #include <iostream.h>
    >
    > int main()
    > {
    > float test;
    > unsigned int test2;
    > test = 1.8;
    > cout << "\n" << test*100.0 << endl;
    > test2 = static_cast<unsigned int>(test*100.0);
    > cout << "\n" << test2 << endl;
    >
    > }
    >
    > The strange thing is that the program returns 180 on the first cout

    (as
    > expected) but it returns 179 on the second ???
    > If I make test 1.7, I get 170 on the first and second cout ???
    > I tried a whole bunch of other values... Sometimes I'm getting what I
    > expected, sometimes not...
    >
    > Can anyone explain this to me ?


    This is caused by the way the float type store number internally. Some
    numbers cannot be exactly represented in floating point format; only a
    approximation of the number is stored. Because of this 1.8*100.0 may
    produce 179.9999952. The reason you see 180.000 is because the result is
    rounded before it is printed. When you change the line that outputs the
    floating point value to:

    cout << "\n" << std::setprecision(10) << test*100.0 << endl;

    You will probably see that test*100.0 is not exactly 180.0

    When casting to in the part behind the decimal point will be truncated
    so the result will be 179.

    This is also the reason why comparing two floating point values with the
    == operator is usually wrong. For example the program below will (most
    likely) output the text "Not equal", because the number 1.23 cannot be
    exactly represented in IEEE-754 floating point format (which most
    implementations use for floating point numbers):

    #include <iostream>
    int main()
    {
    float f = 1.23;

    if(f*2 == 2.46)
    {
    std::cout << "Equal\n";
    }
    else
    {
    std::cout << "Not Equal\n";
    }

    return 0;
    }


    --
    Peter van Merkerk
    peter.van.merkerk(at)dse.nl
     
    Peter van Merkerk, Nov 14, 2003
    #4
  5. GuineaPig

    Li Fanxi Guest

    GuineaPig <> wrote in message news:<bp2gdq$19e$>...
    > Hello,
    >
    > I'm (very) new to c++ and I'm having trouble understanding why this doesn't
    > work. Here's some testcode:
    >
    > #include <iostream.h>
    >
    > int main()
    > {
    > float test;
    > unsigned int test2;
    > test = 1.8;
    > cout << "\n" << test*100.0 << endl;
    > test2 = static_cast<unsigned int>(test*100.0);
    > cout << "\n" << test2 << endl;
    >
    > }
    >
    >
    > The strange thing is that the program returns 180 on the first cout (as
    > expected) but it returns 179 on the second ???
    > If I make test 1.7, I get 170 on the first and second cout ???
    > I tried a whole bunch of other values... Sometimes I'm getting what I
    > expected, sometimes not...
    >
    > Can anyone explain this to me ?
    >
    > Tnx in advance,
    >
    > Tom


    Because float is not an accurate data type.
    For example, an integer 1 add up for 1000 times, you get 1000, but if
    you add float 0.1 for 1000 times, you may get 99.999, not 100.
     
    Li Fanxi, Nov 14, 2003
    #5
  6. GuineaPig

    Ron Natalie Guest

    "Li Fanxi" <> wrote in message news:...

    > Because float is not an accurate data type.


    It pains me when people say this. It leads people to believe that there is some
    non-deterministic thing going on with floats. They're perfectly accurate. The issue
    is not all rational numbers are representable accurately. The confusing issue is that
    while people understand that 1/3 isn't precisely representable in a finite precision
    decimal, they don't undertand that .1 is NOT precisely representable in binary.

    > For example, an integer 1 add up for 1000 times, you get 1000, but if
    > you add float 0.1 for 1000 times, you may get 99.999, not 100.


    ..1 is converted to one of the two nearest representable float values which
    is implementation specific. From then on, the result is deterministic. You
    get 1000 * whatever the converted value is.
     
    Ron Natalie, Nov 14, 2003
    #6
  7. GuineaPig

    Rolf Magnus Guest

    Ron Natalie wrote:

    > .1 is converted to one of the two nearest representable float values
    > which
    > is implementation specific. From then on, the result is
    > deterministic. You get 1000 * whatever the converted value is.


    "1000 * whatever the converted value is" might also not be
    representable.
     
    Rolf Magnus, Nov 14, 2003
    #7
  8. GuineaPig

    Tim Slattery Guest

    "Ron Natalie" <> wrote:

    >
    >"Li Fanxi" <> wrote in message news:...
    >
    >> Because float is not an accurate data type.

    >
    >It pains me when people say this. It leads people to believe that there is some
    >non-deterministic thing going on with floats. They're perfectly accurate. The issue
    >is not all rational numbers are representable accurately. The confusing issue is that
    >while people understand that 1/3 isn't precisely representable in a finite precision
    >decimal, they don't undertand that .1 is NOT precisely representable in binary.


    It's also true that floating point numbers are limited in their
    precision. It will happily store a 45-digit number for you, but as
    (maybe) 1.3456789 time 10 to the 45 power. Digits in excess of the
    precision limit are (I think) lopped off with no error being
    generated.

    --
    Tim Slattery
     
    Tim Slattery, Nov 14, 2003
    #8
  9. GuineaPig

    Ron Natalie Guest

    "Tim Slattery" <> wrote in message news:...

    > It's also true that floating point numbers are limited in their
    > precision. It will happily store a 45-digit number for you, but as
    > (maybe) 1.3456789 time 10 to the 45 power. Digits in excess of the
    > precision limit are (I think) lopped off with no error being
    > generated.
    >

    If you're trying to equate decimal digits as some metric of precision you're
    going to be disappointed.
     
    Ron Natalie, Nov 14, 2003
    #9
  10. GuineaPig

    Fraser Ross Guest

    "Ron Natalie"
    > If you're trying to equate decimal digits as some metric of precision

    you're
    > going to be disappointed.


    I've seen float described as having 7 digit precision and double has 15.

    Fraser.
     
    Fraser Ross, Nov 15, 2003
    #10
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Timo Freiberger
    Replies:
    3
    Views:
    953
    Bob Hairgrove
    Oct 30, 2004
  2. Bo Peng
    Replies:
    11
    Views:
    1,091
    Victor Bazarov
    Oct 20, 2006
  3. er
    Replies:
    6
    Views:
    492
    Andre Kostur
    Sep 14, 2007
  4. ciccio

    int*unsigned int = unsigned?

    ciccio, Jun 4, 2010, in forum: C++
    Replies:
    2
    Views:
    413
    Öö Tiib
    Jun 4, 2010
  5. pozz
    Replies:
    12
    Views:
    745
    Tim Rentsch
    Mar 20, 2011
Loading...

Share This Page