#include <stdio.h>
#include <math.h>
int main () {
float a = 0.0, b = -0.0;
printf("fmax(%f, %f) = %f\n", a, b, fmax(a, b));
}
I get the following result:
gcc f.c -o f -lm
./f
fmax(0.000000, -0.000000) = -0.000000
This (mis)behavior is not documented in the fmax man page. Is there a reasonable explanation for it? And is there a clean (concise) workaround? Also, if both are -0.0, I would like to get -0.0 as the max.
The "problem" is that a == b
. The sign doesn't matter because mantissa (sign put aside) is purely 0. I get 0x80000000
vs 0
So fmax
just checks if a < b
or b < a
(depending on the implementation), and both are false, so either answer is a potential match.
On my gcc version I get fmax(0.0,-0.0)
at 0.0
, but fmax(-0.0,0.0)
is -0.0
.
My attempt at a full workaround, using memcmp
to compare data binary wise in the case of a 0 result.
Even better as suggested, using signbit
which tests if number has negative bit set (regardless of the value):
#include <stdio.h>
#include <math.h>
#include <string.h>
float my_fmax(float a,float b)
{
float result = fmax(a,b);
if ((result==0) && (a==b))
{
/* equal values and both zero
the only case of potential wrong selection of the negative
value. Only in that case, we tamper with the result of fmax,
and just return a unless a has negative bit set */
result = signbit(a) ? b : a;
}
return result;
}
int main () {
float a = -0.0, b = 0.0;
printf("fmax(%f, %f) = %f\n", a,b, my_fmax(a, b));
a = 0.0;
printf("fmax(%f, %f) = %f\n", a,b, my_fmax(a, b));
a = b = -0.0;
printf("fmax(%f, %f) = %f\n", a,b, my_fmax(a, b));
a = 1.0;
printf("fmax(%f, %f) = %f\n", a,b, my_fmax(a, b));
a = -1.0;
printf("fmax(%f, %f) = %f\n", a,b, my_fmax(a, b));
b = 0.0;
printf("fmax(%f, %f) = %f\n", a,b, my_fmax(a, b));
}
result (I think I covered all the cases):
fmax(-0.000000, 0.000000) = 0.000000
fmax(0.000000, 0.000000) = 0.000000
fmax(-0.000000, -0.000000) = -0.000000
fmax(1.000000, -0.000000) = 1.000000
fmax(-1.000000, -0.000000) = -0.000000
fmax(-1.000000, 0.000000) = 0.000000
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With