Bug 631986

Summary: gcc "-ansi" causes double d = 0.1; if (d != 0.1) { fail } to trigger
Product: [Fedora] Fedora Reporter: Caolan McNamara <caolanm>
Component: gccAssignee: Jakub Jelinek <jakub>
Status: CLOSED NOTABUG QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: medium Docs Contact:
Priority: low    
Version: rawhideCC: denis.arnaud_fedora, jakub, srl
Target Milestone: ---   
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2010-09-08 20:44:18 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On:    
Bug Blocks: 631403    
Attachments:
Description Flags
gcc -m32 -ansi test.c none

Description Caolan McNamara 2010-09-08 19:48:25 UTC
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 20:09:07 UTC
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 20:44:18 UTC
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 19:18:43 UTC
Fixed in ICU upstream http://bugs.icu-project.org/trac/ticket/7932 ( Should ICU be an available external bug type here?)