tags:

views:

214

answers:

6
#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?

+12  A: 

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.

Peter G.
So much verbiage to wade through, and the essential fact of float precision isn't obvious at all. I don't know why this is so highly upvoted.
Mark Ransom
@Mark I added explicit precision data now.
Peter G.
+7  A: 

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

Carl Norum
uh-oh!! bad bad bad!! thanks.
Webbisshh
but should it increase or decrease? i suppose it should have decreased?
Webbisshh
I think it should round to the nearest available float number. I leave that as an exercise :-).
Peter G.
Precision loss is precision loss. The represented value is quantized, and can and will fall to either side of the intended value. IEEE-754 specified some rounding modes that might influence this, but that would depend on your compiler providing a way to access them for a compile time constant.
RBerteig
Cool i think i should read the specification carefully. Thanks anyways!
Webbisshh
@Webbisshh: rounding in C99 is controlled via fesetround() / fesetenv() / feupdateenv()
ninjalj
@ RBerteig I agree. However, I have to remark that "round to nearest" is the default mode specified by IEEE-754.
Peter G.
@ninjali: The `<fenv.h>` functions effect rounding at runtime; this conversion may occur at compile time and will not necessarily be effected by their use.
Stephen Canon
@Peter G, IMHO, Round to nearest is the only mode that makes sense for translating source text, but you never know what a standards committee will decide. ;-).
RBerteig
+2  A: 

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; 
}
C Johnson
+20  A: 

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.

Stephen Canon
Wow! many thanks!!
Webbisshh
+1, Nicely explained.
RBerteig
+1  A: 

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
anon
Sometimes the FPU is only single precision. Particularly SIMD implementations are often single precision.
Carl Norum
They may also be dramatically faster; if you're writing code for a smartphone, for example -- on some current ARM processors, float can be 8 (or more) times faster than double.
Stephen Canon
@Stephen Sure. But I suspect the majority of people here are using 80x86 architectures, and/or think that floats are naturally faster than doubles without having read the processor spec sheet or done any testing on whether the performance difference matters on their app. Speaking personally, I always prefer correctness (precision) over speed, until I'm forced to sacrifice it.
anon
"I simply don't understand why people use floats"Also keep in mind space. If you're storing N-million floating-point numbers, you potentially save N megabytes of RAM.
Rooke
The other thing worth noting is that using `double` doesn't make this problem go away; it only changes the size of the numbers for which it occurs. Representation error is inherent to the use of any fixed-size type.
Stephen Canon
@Rooke But I don't think most people are storing millions of numbers that either - I know I never have. It seems to me that many (most?) questions here on SO use float when they could much better have used double.
anon
@Stephen Of course - but using float instead of double for no particular reason will make you run into the problem more often.
anon
Using 64-bit integers makes overflow bugs less likely than if you use 32-bit integers; would you say that you "simply don't understand why people use 32-bit integers"?
Stephen Canon
@Stephen I would use whatever integer size was natural for what I wanted my application to do. The natural real number type for the kind of applications I write, and I suspect for the majority of programmers here, is a double.
anon
I agree with Neil 100 % here. Floats are best left for special purposes. Besides this simple example they can easily screw up numeric code in unforeseen ways if it is not crafted very carefully.
Peter G.
@Peter G., @Neil Butterworth: that's more or less my point, though. *no* type should be used without consideration. The solution isn't "always use double"; the solution is "think about what you're doing, and use the appropriate type".
Stephen Canon
A: 

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
chaitanyavarma