Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does the C == operator decide whether or not two floating point values are equal?

Today I was tracking down why my program was getting some unexpected checksum-mismatch errors, in some code that I wrote that serializes and deserializes IEEE-754 floating-point values, in a format that includes a 32-bit checksum value (which is computed by running a CRC-type algorithm over the bytes of the floating-point array).

After a bit of head-scratching, I realized the problem was the 0.0f and -0.0f have different bit-patterns (0x00000000 vs 0x00000080 (little-endian), respectively), but they are considered equivalent by the C++ equality-operator. So, the checksum-mismatch errors happened because my checksum-calculating algorithm picked up the difference between those two bit-patterns, while certain other parts of my codebase (that use floating point equality testing, rather than looking at the values byte-by-byte) did not make that distinction.

Okay, fair enough -- I should probably have known better than to do floating-point equality testing anyway.

But this got me thinking, are there other IEEE-754 floating point values that are considered equal (according to the C == operator) but have different bit-patterns? Or, to put it another way, how exactly does the == operator decide whether two floating-point values are equal? Newbie me though it was doing something like memcmp() on their bit-patterns, but clearly it's more nuanced than that.

Here's a code example of what I mean, in case I wasn't clear above.

#include <stdio.h>

static void PrintFloatBytes(const char * title, float f)
{
   printf("Byte-representation of [%s] is: ", title);
   const unsigned char * p = (const unsigned char *) &f;
   for (int i=0; i<sizeof(f); i++) printf("%02x ", p[i]);
   printf("\n");
}

int main(int argc, char ** argv)
{
   const float pzero = -0.0f;
   const float nzero = +0.0f;
   PrintFloatBytes("pzero", pzero);
   PrintFloatBytes("nzero", nzero);
   printf("Is pzero equal to nzero?  %s\n", (pzero==nzero)?"Yes":"No");
   return 0;
}
like image 832
Jeremy Friesner Avatar asked Jun 07 '11 00:06

Jeremy Friesner


1 Answers

It uses the IEEE-754 equality rules.

  • -0 == +0
  • NaN != NaN
like image 200
SLaks Avatar answered Oct 04 '22 21:10

SLaks