4

I tried running this simple code on ideone.com

#include<stdio.h>
int main()
{
    double a = 0.7f;  // Notice: f for float
    double b = 0.7;

    if (a == b) 
        printf("Identical\n"); 
    else 
        printf("Differ\n");

    return 0;
}

With gcc-5.1 the output is Identical

With clang 3.7 the output is Differ

So it seems gcc ignores the f in 0.7f and treats it as a double while clang treats it as a float.

Is this a bug in one of the compilers or is this implementation dependent per standard?

Note: This is not about floating point numbers being inaccurate. The point is that gcc and clang treats this code differently.

Support Ukraine
  • 42,271
  • 4
  • 38
  • 63
  • 4
    @WeatherVane - I don't think it is a dup. This is not about floats being inaccurate. It's about gcc and clang treating `0.7f` differently when used for initializing a double. – Support Ukraine Jul 04 '16 at 08:27
  • a [similar question](http://stackoverflow.com/questions/38178368/floating-point-constant) was asked an hour ago, which was marked as dup. Its comments might be relevant to this one. – Weather Vane Jul 04 '16 at 08:29
  • 1
    When it comes to questions like this, it is not a matter about _if_ it is a dup, but which dup to pick. If the OP don't like the proposed dup, then _they_ can do the research and go find one. This question has been asked numerous times before on SO, in different flavours. – Lundin Jul 04 '16 at 08:41
  • I can't repro this, GCC 5.1 reports "Differ" when compiling for x86-32 or x86-64. – Cody Gray - on strike Jul 04 '16 at 14:50
  • @CodyGray - I used ideone.com for this test - first selecting `gcc c` and then `clang c`. I also compiled it as `c++` which showed that gcc did it differently for `c` and `c++`. – Support Ukraine Jul 04 '16 at 16:43
  • @CodyGray - gcc version: http://ideone.com/3RBzhC - clang version: http://ideone.com/KLv4wu and c++ version gcc: http://ideone.com/8MMPzp `gcc c` shows `identical` while `c clang` and `c++ gcc` shows differ. I wonder whether `c gcc` have a bug as `0.7f`should be a float - i.e. not a double. – Support Ukraine Jul 04 '16 at 16:48
  • @Lundin - If you can provide a link to an SO question asking why `gcc` and `clang`differs or a link to an SO question telling that `0.7f` may be interpreted as a `double`, I'll delete this question asap. – Support Ukraine Jul 04 '16 at 16:54
  • Hmm, sure enough. Interesting. I only get a repro on GCC 5.1 when (A) targeting x86-32 (`-m32`) *and* (B) requesting C99 standards support (`-xc -std=c99`). If those flags are not specified, GCC 5.1 returns "differ", just like all other compilers. Not sure what C99 changed here, but since it doesn't change 64-bit builds, I'm betting it has more to do with the 32-bit x87's internal floating-point registers that have 80-bit precision. – Cody Gray - on strike Jul 05 '16 at 10:25

2 Answers2

3

The C standard allows floating point operations use higher precision than what is implied by the code during compilation and execution. I'm not sure if this is the exact clause in the standard but the closest I can find is §6.5 in C11:

  1. A floating expression may be contracted, that is, evaluated as though it were a single operation, thereby omitting rounding errors implied by the source code and the expression evaluation method

Not sure if this is it, or there's a better part of the standard that specifies this. There was a huge debate about this a decade ago or two (the problem used to be much worse on i386 because of the internally 40/80 bit floating point numbers in the 8087).

Art
  • 19,807
  • 1
  • 34
  • 60
2

The compiler is required to convert the literal into an internal representation which is at least as accurate as the literal. So gcc is permitted to store floating point literals internally as doubles. Then when it stores the literal value in 'a' it will be able to store the double. And clang is permitted to store floats as floats and doubles as doubles.

So it's implementation specific, rather than a bug.

Addendum: For what it is worth, something similar can happen with ints as well

int64_t val1 = 5000000000;
int64_t val2 = 5000000000LL;
if (val1 != val2) { printf("Different\n"); } else { printf("Same\n"); }

can print either Different or Same depending on how your compiler treats integer literals (though this is more particularly an issue with 32 bit compilers)

Tom Tanner
  • 9,244
  • 3
  • 33
  • 61
  • To me the `int` example is not the same. The `int`example is a (32 bit) overflow issue. The `0.7f` example isn't a overflow as a `double` can represent all values that a `float`can represent. – Support Ukraine Jul 04 '16 at 09:57
  • True, it's not the same, but it is similar. It's to do with how the compiler deals with literals resulting in different behaviour on different compilers. – Tom Tanner Jul 04 '16 at 14:16
  • There's no overflow in literals. The type of the literal is whatever it needs to be to represent the value (or the program is ill-formed). – Kerrek SB Jul 05 '16 at 13:06
  • The compiler is not required to notify you if your literal overflows. And most don't. – Tom Tanner Jul 05 '16 at 20:37