RubyDubee
RubyDubee

Reputation: 2446

union consisting of float : completely insane output

#include <stdio.h>

union NumericType
{
    float value;
    int intvalue;
}Values;

int main()
{
    Values.value = 1094795585.00;
    printf("%f \n",Values.value);
    return 0;
}

This program outputs as :

1094795648.000000 

Can anybody explain Why is this happening? Why did the value of the float Values.value increase? Or am I missing something here?

Upvotes: 4

Views: 4418

Answers (7)

Olof Forshell
Olof Forshell

Reputation: 3274

It only complicates things to speak of decimal digits because this is binary arithmetic. To explain this we can begin by looking at the set of integers in the single precision format where all the integers are representable. Since the single precision format has 23+1=24 bits of precision that means that the range is

0 to 2^24-1

This is not good or detailed enough for explaining so I'll refine it further to

0 to 2^24-2^0 in steps of 2^0

The next higher set is

0 to 2^25-2^1 in steps of 2^1

The next lower set is

0 to 2^23-2^-1 in steps of 2^-1

Your number, 1094795585 (0x41414141 in hex), falls in the range that has a maximum of slightly less than 2^31 =. That range can be expressed in detail as 0 to 2^31-2^7 in steps of 2^7. It's logical because 2^31 is 7 powers of 2 greater than 24. Therefore the increments must also be 7 powers of 2 greater.

Looking at the "next lower" and "next higher" values mentioned in another post we see that the difference between them is 128 i e 2^7.

There's really nothing strange or weird or funny or even magic about this. It's actually absolutely clear and quite simple.

Upvotes: 0

chaitanyavarma
chaitanyavarma

Reputation: 315

By default a printf of float with %f will give precision 6 after the decimal. If you want a precision of 2 digits after the decimal use %.2f. Even the below gives same result

#include <stdio.h>
union NumericType
{
    float value;
    int intvalue;
}Values;

int main()
{
    Values.value = 1094795585;
    printf("%f \n",Values.value);
    return 0;
}

Result 
./a.out
1094795648.000000

Upvotes: 0

Peter G.
Peter G.

Reputation: 15144

A float isn't as precise as you would like it to be. Its mantissa of an effective 24 bit only provides a precision of 7-8 decimal digits. Your example requires 10 decimal digits precision. A double has an effective 53 bit mantissa which provides 15-16 digits of precision which is enough for your purpose.

Upvotes: 14

anon
anon

Reputation:

I simply don't understand why people use floats - they are often no faster than doubles and may be slower. This code:

#include <stdio.h>

union NumericType
{
    double value;
    int intvalue;
}Values;

int main()
{
    Values.value = 1094795585.00;
    printf("%lf \n",Values.value);
    return 0;
}

produces:

1094795585.000000

Upvotes: 1

Stephen Canon
Stephen Canon

Reputation: 106277

First off, this has nothing whatsoever to do with the use of a union.

Now, suppose you write:

int x = 1.5;
printf("%d\n", x);

what will happen? 1.5 is not an integer value, so it gets converted to an integer (by truncation) and x so actually gets the value 1, which is exactly what is printed.

The exact same thing is happening in your example.

float x = 1094795585.0;
printf("%f\n", x);

1094795585.0 is not representable as a single precision floating-point number, so it gets converted to a representable value. This happens via rounding. The two closest values are:

1094795520 (0x41414100) -- closest `float` smaller than your number
1094795585 (0x41414141) -- your number
1094795648 (0x41414180) -- closest `float` larger than your number

Because your number is slightly closer to the larger value (this is somewhat easier to see if you look at the hexadecimal representation), it rounds to that value, so that is the value stored in x, and that is the value that is printed.

Upvotes: 28

C.J.
C.J.

Reputation: 16111

floats only have 7 digits of precision See this link for more details: link text

When I do this, I get the same results:

int _tmain(int argc, _TCHAR* argv[])
{
    float f = 1094795585.00f; 
    //        1094795648.000000
    printf("%f \n",f); 
    return 0; 
}

Upvotes: 2

Carl Norum
Carl Norum

Reputation: 225112

It's because your float type doesn't have the precision to display that number. Use a double.

Upvotes: 7

Related Questions