In C, is there a guarantee that two doubles whose values are equal (double1 == double2
) will have identical bit patterns?

- 587
- 1
- 5
- 18
-
It's not really a matter of the language but of the pc architecture itself. If you're into it, you can read on numerical analysis, in any case just remember that when comparing floats you should check their difference against a negligible value. That value should make sense to your application, i.e. while it does make some sense to compare |a - b| < 0.001 when you're interested in significance of 1 fractional digit, it does not make any sense at all when comparing numbers like 10^-6, since anything below 0.001 would be considered equal. – mewa Oct 07 '16 at 03:20
-
Note: Even with the same `double` _value_: +0.0 and -0.0, some operations give different results: [What operations and functions on +0.0 and -0.0 give different arithmetic valued results?](http://stackoverflow.com/q/25332133/2410359) – chux - Reinstate Monica Oct 07 '16 at 03:21
-
I smell an XY problem. **Why** do you want to rely on that? – too honest for this site Oct 07 '16 at 13:12
-
I'm creating a small JVM-like bytecode interpreter where I'm storing both doubles and pointers to objects in uint64_t's using NaN tagging. Obviously, equal bit patterns would guarantee equality for both numbers and objects, but if the bit patterns of numbers can differ while the values remain the same, then I obviously can't rely only on the bit pattern. – Sheldon Juncker Oct 08 '16 at 05:57
-
Just remembered that NaNs won't compare as equal anyway. – Sheldon Juncker Oct 08 '16 at 14:14
2 Answers
There is no such guarantee.
For example, in IEEE floating point format, there exists the concept of negative 0. It compares equal to positive 0 but has a different representation.
Here's an example of that:
#include <stdio.h>
int main()
{
unsigned long long *px, *py;
double x = 0.0, y = -0.0;
px = (unsigned long long *)&x;
py = (unsigned long long *)&y;
printf("sizeof(double)=%zu\n",sizeof(double));
printf("sizeof(unsigned long long)=%zu\n",sizeof(unsigned long long));
printf("x=%f,y=%f,equal=%d\n",x,y,(x==y));
printf("x=%016llx,y=%016llx\n",*px,*py);
return 0;
}
Output:
sizeof(double)=8
sizeof(unsigned long long)=8
x=0.000000,y=-0.000000,equal=1
x=0000000000000000,y=8000000000000000
EDIT:
Here's a revised example that doesn't rely on type punning:
#include <stdio.h>
void print_bytes(char *name, void *p, size_t size)
{
size_t i;
unsigned char *pdata = p;
printf("%s =", name);
for (i=0; i<size; i++) {
printf(" %02x", pdata[i]);
}
printf("\n");
}
int main()
{
double x = 0.0, y = -0.0;
printf("x=%f,y=%f,equal=%d\n",x,y,(x==y));
print_bytes("x", &x, sizeof(x));
print_bytes("y", &y, sizeof(y));
return 0;
}
Output:
x=0.000000,y=-0.000000,equal=1
x = 00 00 00 00 00 00 00 00
y = 00 00 00 00 00 00 00 80
You can see here the difference in representation between the two. One has the sign bit set while the other doesn't.

- 205,898
- 23
- 218
- 273
-
Note: With various IEEE _decimal_ FP formats there are many redundant bit patterns with the same value. E.g. [decimal64 floating-point format](https://en.wikipedia.org/wiki/Decimal64_floating-point_format) – chux - Reinstate Monica Oct 07 '16 at 03:17
-
-
1Note that you shouldn't type pun via dereferencing, as this breaks strict aliasing. From C99 onwards, you can use `memcpy` or unions. – Simon Byrne Oct 07 '16 at 08:53
Yes, with the exception of zero. There is only one way to represent a particular IEEE float or double value. If there were two ways to represent the same value then that would be wasteful and the IEEE formats are very efficient.
Zero is a special case because there are positive and negative values of zero and they will compare equal, and they are equal for most purposes. There are a few rare cases (1/0) where they will give different results - positive versus negative infinity.
The previous answer focused unnecessarily on the zero case and failed, as far as I can tell, to answer the case for the other 4 billion floats and 16 billion billion doubles.

- 3,284
- 29
- 38
-
-
There are some geometries where +infinity and -infinity are considered equal but IEEE math does not treat them as such. There are also NaNs which are considered unequal to everything, even themselves. So yes, +0 and -0 are the only exceptions. – Bruce Dawson Oct 09 '16 at 17:32