c - Why does fmax(a, b) return the smaller (negative) zero and how to cleanly workaround it? -


#include <stdio.h> #include <math.h>  int main () {     float = 0.0, b = -0.0;     printf("fmax(%f, %f) = %f\n", a, b, fmax(a, b)); } 

i following result:

gcc f.c -o f -lm ./f fmax(0.000000, -0.000000) = -0.000000 

this (mis)behavior not documented in fmax man page. there reasonable explanation it? , there clean (concise) workaround? also, if both -0.0, -0.0 max.

the "problem" a == b. sign doesn't matter because mantissa (sign put aside) purely 0. 0x80000000 vs 0

so fmax checks if a < b or b < a (depending on implementation), , both false, either answer potential match.

on gcc version fmax(0.0,-0.0) @ 0.0, fmax(-0.0,0.0) -0.0.

my attempt @ full workaround, using memcmp compare data binary wise in case of 0 result.

even better suggested, using signbit tests if number has negative bit set (regardless of 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 , both 0           case of potential wrong selection of negative            value. in case, tamper result of fmax,           , return unless has negative bit set */         result = signbit(a) ? b : a;    }    return result; }  int main () {     float = -0.0, b = 0.0;      printf("fmax(%f, %f) = %f\n", a,b, my_fmax(a, b));     = 0.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));     = 1.0;     printf("fmax(%f, %f) = %f\n", a,b, my_fmax(a, b));     = -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 covered 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 

Comments