Bug 631986 - gcc "-ansi" causes double d = 0.1; if (d != 0.1) { fail } to trigger
gcc "-ansi" causes double d = 0.1; if (d != 0.1) { fail } to trigger
Status: CLOSED NOTABUG
Product: Fedora
Classification: Fedora
Component: gcc (Show other bugs)
rawhide
All Linux
low Severity medium
: ---
: ---
Assigned To: Jakub Jelinek
Fedora Extras Quality Assurance
:
Depends On:
Blocks: 631403
  Show dependency treegraph
 
Reported: 2010-09-08 15:48 EDT by Caolan McNamara
Modified: 2010-09-21 15:18 EDT (History)
3 users (show)

See Also:
Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
Environment:
Last Closed: 2010-09-08 16:44:18 EDT
Type: ---
Regression: ---
Mount Type: ---
Documentation: ---
CRM:
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---


Attachments (Terms of Use)
gcc -m32 -ansi test.c (289 bytes, text/plain)
2010-09-08 15:48 EDT, Caolan McNamara
no flags Details


External Trackers
Tracker ID Priority Status Summary Last Updated
Gentoo 318393 None None None Never

  None (edit)
Description Caolan McNamara 2010-09-08 15:48:25 EDT
Created attachment 446074 [details]
gcc -m32 -ansi test.c

Version-Release number of selected component (if applicable):
gcc-4.5.1-3.fc14

How reproducible:
100%

Steps to Reproduce:
1. gcc -m32 -ansi test.c
2. ./a.out
where test.c is

#include <stdio.h>

int main(void)
{
    double d=0.1;

    if(d!=0.1)
	printf("unexpected!\n");

    return 0;
}
  
Actual results:
"unexpected!"

Expected results:
nothing

Additional info:
caught by icu make check, so this didn't happen earlier in the F-14 cycle

without "-ansi" this behaves as expected. Seems odd that -ansi has an effect on this.
Comment 1 Denis Arnaud 2010-09-08 16:09:07 EDT
I'm not sure about the C/C++ standards, but it is usually a bad idea to strictly compare two floats or doubles. It is recommended to compare that two floats/doubles are roughly equal, with a given accuracy of epsilon (e.g., 1e-3).

That statement comes from years of experience with several major OLTP applications on different Unices (HP-UX, SunOS, Linux) running on different hardware platforms in production.

Sometimes, a given application, where we compared two floats, runned two or three years in production with 10tps (transactions per second) 24x7, without any problem. Then, suddenly, nobody could explain why, but the application started to fail: the floats became no longer equal (and sometimes, not not equal at the same time!).

Hence, we have implemented the epsilon trick everywhere we needed to compare two floats/doubles. And we have been able to sleep quietly ever since...


That's just my $0.02
Comment 2 Jakub Jelinek 2010-09-08 16:44:18 EDT
i?86-linux is a FLT_EVAL_METHOD 2 target (because of the insane i?87 hw), and that requires that for strict standard conformance all operations and constants are supposed to be evaluated in precision of long double.  d is a double variable, so the constant needs to be casted to double precision, so it is evaluated as
double d = 0.1;
if ((long double) d != 0.1L)
and those constants are different.
If you write it as if(d!=(double)0.1), it will be equal.
GCC 4.5 implement this standard conformant mode.  There is the -fexcess-precision={fast,standard} option to select behavior, with standard being the default for -std={c89,c9*,iso*} and fast otherwise.  Of course for FLT_EVAL_METHOD 0 targets like x86-64 this doesn't make difference.
What Denis wrote above is a reasonable recommendation in any case.
Comment 3 Steven R. Loomis 2010-09-21 15:18:43 EDT
Fixed in ICU upstream http://bugs.icu-project.org/trac/ticket/7932 ( Should ICU be an available external bug type here?)

Note You need to log in before you can comment on or make changes to this bug.