You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Warning: comparing floating point with == or != is unsafe [-Wfloat-equal] #37
Compiling with GCC using -Wfloat-equal turned on, I get the following warnings:
printf.c:346:18: warning: comparing floating point with == or != is unsafe [-Wfloat-equal]
printf.c:363:20: warning: comparing floating point with == or != is unsafe [-Wfloat-equal]
The code does has a compare to 0.5
Any ideas on how to resolve this?
Thank you for creating this wonderful function!
The simplest way would probably be to rewrite it to use something like:
// presuming diff is positiveif ( diff>0.5 ) {
} elseif ( !(diff<0.5) ) {
// if not > and not <, then it must be ==// (but this will also happen if diff is NaN)
}
I am not sure how to check for NaN without including <math.h>. So to get an actual comparison, I believe you would have to do something like this:
boolis_zero_point_five(doublenum)
{
// private union, used to get the// bitwise representation of the floatuniondouble_to_u32
{
uint64_tas_uint;
doubleas_float;
};
uniondouble_to_u32zero_point_five= { .as_float=0.5 };
uniondouble_to_u32value= { .as_float=num };
returnvalue.as_uint==zero_point_five.as_uint;;
}
Basically, this uses a union to get an unsigned 64 bit representation of the double, and then compares the integers.
Due to the fact that gcc must account for NaNs and perhaps other floating point exceptions, it cannot optimize !(x < 0.5) && !(x > 0.5) to the equivalent of x != 0.5. However, although the union implementation doesn't produce warnings, it presumes that sizeof(double) is 8 (which should be true on practically all platforms).
thanks a lot for bringing this problem to attention.
I'm aware of this "bug" and I don't like it either. Comparing floats to discrete numbers is never a sure/good thing.
The whole ftoa routine needs further testing and minor refactoring. This is still on the todo list.
Anyway, this is just a warning but if you need to be warning free, a construct of greater/smaller comparisons might help - as a quick fix.
No, I believe the C standard says nothing about the size, although IEEE 754 / IEC 60559 specifies float and double as 32 and 64-bit.
Perhaps my comment was unnecessarily complicated, and the most reasonable option would be to suppress the warning in GCC? This should leave it to compiler to produce the correct code for a given platform, regardless of the size of floats:
// doesn't have to be a separate methodstaticinlinebooldouble_are_equal(doublea, doubleb)
{
// temporarily suppress "comparing float with == is unsafe"// (we really want to check exactly against 0.5)#ifdef__GNUC__#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wfloat-equal"
#endifreturna==b;
#ifdef__GNUC__#pragma GCC diagnostic pop
#endif
}
Activity
vgrudenic commentedon Dec 23, 2018
The simplest way would probably be to rewrite it to use something like:
I am not sure how to check for
NaNwithout including<math.h>. So to get an actual comparison, I believe you would have to do something like this:Basically, this uses a
unionto get an unsigned 64 bit representation of thedouble, and then compares the integers.This gives no warnings and produces rather simple code in gcc. With optimizations enabled, GCC simply compares the value to
0x3FE0000000000000, which is the IEEE-754 representation of0.5:This can be generalized to:
Due to the fact that gcc must account for
NaNs and perhaps other floating point exceptions, it cannot optimize!(x < 0.5) && !(x > 0.5)to the equivalent ofx != 0.5. However, although theunionimplementation doesn't produce warnings, it presumes thatsizeof(double)is 8 (which should be true on practically all platforms).mpaland commentedon Dec 23, 2018
Hello @HarjitSi,
thanks a lot for bringing this problem to attention.
I'm aware of this "bug" and I don't like it either. Comparing floats to discrete numbers is never a sure/good thing.
The whole
ftoaroutine needs further testing and minor refactoring. This is still on the todo list.Anyway, this is just a warning but if you need to be warning free, a construct of greater/smaller comparisons might help - as a quick fix.
mpaland commentedon Dec 24, 2018
@vgrudenic , thanks a lot for your suggestion.
Is
doublereally and always 8 bytes on any platform?I have to investigate this a little further...
Merry christmas! 🎄
vgrudenic commentedon Dec 24, 2018
Hi, merry christmas to you too! 🎄😃
No, I believe the C standard says nothing about the size, although IEEE 754 / IEC 60559 specifies float and double as 32 and 64-bit.
Perhaps my comment was unnecessarily complicated, and the most reasonable option would be to suppress the warning in GCC? This should leave it to compiler to produce the correct code for a given platform, regardless of the size of floats: