You may try the following hack (on a little endian system):
typedef union {
double d;
struct { unsigned long long m:52, e:11, s:1; } x;
} double_union;
typedef union {
float f;
struct { unsigned long m:23, e:8, s:1; } x;
} float_union;
void write_bits(long e, unsigned long long m, int is_float)
{
size_t b = is_float ? 23 : 52;
long bias = is_float ? 127 : 1023;
size_t n = sizeof(m)*8;
unsigned long long mask = (0x1ull << (n-1));
printf("%s.", !e && !m ? "0" : "1");
m <<= (n-b);
while(b-- > 0)
{
printf("%s", (m & mask) ? "1" : "0");
m <<= 1;
}
if (e) printf(" 2^%d", e-bias);
}
void write_float(float_union u)
{
printf("%s", u.x.s ? "-" : "+");
unsigned long e = u.x.e;
unsigned long m = u.x.m;
write_bits(e, m, 1);
printf("\n");
}
void write_double(double_union u)
{
printf("%s", u.x.s ? "-" : "+");
unsigned long e = u.x.e;
unsigned long long m = u.x.m;
write_bits(e, m, 0);
printf("\n");
}
int main()
{
float a = 0.7;
if(0.7 > a) printf("Hi\n");
else printf("Hello\n");
double_union du;
float_union fu;
fu.f = 0.7;
write_float(fu);
du.d = 0.7;
write_double(du);
du.d = fu.f; write_double(du);
return 0;
}
The output on my little endian system with 4-byte float and 8-byte double is
Hi
+1.01100110011001100110011 2^-1
+1.0110011001100110011001100110011001100110011001100110 2^-1
+1.0110011001100110011001100000000000000000000000000000 2^-1
This shows that the two values are not equal anymore.
0.7
is of type double.
0.7 > a
promotes the
float a
value to a
double
value. This results in the above mentioned different values. The
double 0.7
is indeed greater than the
float 0.7f
since the
float
value is promoted to the
double
value for comparison.
What to learn from this:
never mix number domains, especially for floating point numbers.
See also
What Every Computer Scientist Should Know About Floating-Point Arithmetic[
^].
Cheers
Andi