Casting double to float - compiler bug?

Discussion in 'C Programming' started by Jonathan Fielder, Aug 6, 2003.

  1. Hi,

    My program (below) casts a double (which is in range for a float) to a
    float. As far as I know this should give me the nearest representable
    float, which will loose some precision. I then test for a NAN by comparing
    my float to itself (is this correct?), and I get different behaviour with
    different compilers. Have I done something that is undefined, or is this a
    compiler bug?

    Thanks,

    Jon.

    GCC:

    $ ./a.exe
    *** NOT A NAN ***
    y = 1.56723856925964355469

    MS Visual C++:

    $ ./single
    *** NAN ***
    y = 1.56723856925964360000


    #include <stdio.h>

    int main(void) {
    /* set x to double that is in RANGE for single precision */
    double x = 1.5672385729857;
    /* cast double to float, loosing PRECISION */
    float y = (float) x;

    /* test for bad y - test for NAN */
    if (y != y) {
    printf("*** NAN ***\n\n");
    printf("y = %10.20f\n", y);
    }
    else {
    printf("*** NOT A NAN ***\n\n");
    printf("y = %10.20f\n", y);
    }
    }
     
    Jonathan Fielder, Aug 6, 2003
    #1
    1. Advertisements

  2. Jonathan Fielder

    Dan Pop Guest

    C89 doesn't specify anything about NANs, but this is not an issue for your
    program, which doesn't involve any NANs, your value being in range for
    both double and float.
    I can see no way this program could execute the if branch. If you're
    x86-literate, have a look at the assembly code generated by the
    compiler. I suspect the compiler has somehow managed to compare the
    value before truncation with the value after truncation and found them
    different (no surprise!).

    You may also want to check the faulty compiler's documentation for an
    option disabling certain illegal floating point optimisations that might
    be enabled by default (a la gcc's -ffloat-store).

    Dan
     
    Dan Pop, Aug 6, 2003
    #2
    1. Advertisements

  3. Under MS VC6, if Microsoft extensions are enabled (by default
    (/Ze)), the wrong branch is taken. The comparison seems to be
    made as you say (I'm too lazy to look at the assembly output -
    maybe the OP will want to). Note also that y == x evaluates to
    true in this case.

    Under MS VC6 If Microsoft extensions are disabled (/Za), the
    correct branch is taken.

    (To the OP) It is a well-known problem that x86 processors do not
    cast from greater precision to lesser precision properly by
    default. Floats are 32 bits, doubles are 64 bits, and
    intermediate results are stored in 80 bit floating-point
    registers. Sometimes values are reloaded from memory at
    inappropriate times, such as the case at hand. In essence, y in
    an 80-bit floating-point register (maintaining the value of x) is
    compared with the 32-bit value of y, and they compare not equal.
    If /Za is set, then this behavior is supressed, and the cast is
    performed correctly.

    Regards,
    Bruce Wheeler
     
    Bruce Wheeler, Aug 6, 2003
    #3
  4. Jonathan Fielder

    Tim Prince Guest

    Without disagreeing with other respondents, I'd like to point out that gcc
    is unusual in not evaluating (y != y) with standard optimizations, at
    compile time, by default. If you issue the options -O -ffast-math, it may
    choose to evaluate that expression as 0 at compile time. In your case, it
    will get the same result with evaluation at run time. The C99 standard,
    AFAIK, requires you to use the isnan() function to avoid making this code
    depend on compiler options and implementation. Prior to C99, the question
    was not addressed, other than by gcc conforming to the informed consensus
    of experts.
    I would not be surprised if the result you got with your Microsoft compiler
    depended on the optimization level.
     
    Tim Prince, Aug 7, 2003
    #4
  5. Thanks!

    Jon.
     
    Jonathan Fielder, Aug 7, 2003
    #5
    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.