strange rounding

Started by
8 comments, last by mike74 18 years, 7 months ago
I have the following code: cout << int((log(8)/log(2))) << endl; float somefloat = log(8)/log(2); cout << int(somefloat) << endl; Anyone know why it prints out two different numbers? mike http://www.coolgroups.com/
Mike C.http://www.coolgroups.com/zoomer/http://www.coolgroups.com/ez/
Advertisement
In my opinion log(8)/log(2) = 3 [smile]

The problem can be related to the fact that log(8)/log(2) is something equal 3 minus a little tollerance caused by float precision so when you cast to int
( int i = (int)f ) you cut the mantissa and you get 2 instead of 3.
Yeah, a float->int cast always rounds down. Here it looks like you need to convert to the nearest int.
What values does it actually give?

The best explanation I can think of is that in the 1st case because the result is cast to an integer it uses the default log function which returns a double, but in the second case it uses the logf function which returns float. That would cost you precision which might cause it to round differently. That seems to be odd behaviour and I don't know if it's standard or not. What compiler are you using? You can always check the assembler code produced and see what the difference is.
It prints:

2
3

Also, I'm using Dev-cpp. Please try it out and let me know if you get the same results.

mike
http://www.coolgroups.com/
Mike C.http://www.coolgroups.com/zoomer/http://www.coolgroups.com/ez/
In the first case you're casting double to int, a double which is slightly less than 3, giving the result of 2.
In the second case you're implicitly casting (compiler should warn you) from double to float in assigning to 'somefloat', in which the rounding will give the float a value of 3. So when you come to cast from the float to int, it'll be 3.
If this was true, then why does the following print 3?

double somedouble = log(8)/log(2);
cout << int(somedouble) << endl;


Quote:Original post by c2_0
In the first case you're casting double to int, a double which is slightly less than 3, giving the result of 2.
In the second case you're implicitly casting (compiler should warn you) from double to float in assigning to 'somefloat', in which the rounding will give the float a value of 3. So when you come to cast from the float to int, it'll be 3.


Mike C.http://www.coolgroups.com/zoomer/http://www.coolgroups.com/ez/
It's possible that one case is pulling the result off the FPU stack as a double before converting it to float, whereas the other case is pulling it off as a float in the first place.

It doesn't really matter, though. The bottom line is, you're converting a float to an int, and it's giving you problems. That's what happens when you count on floating-point numbers to be exact. Lesson learned: from now on, if you need to go from a float to an int, round it instead of truncating it.
Internally it would be using extended precision (80bits - long double).

When you assign to the double, that internal result will get rounded to 3.

So, I'll correct myself. It would be the conversion from the extended precision to either double or float which rounds to 3, not the conversion from double to float (although, the principle is the same ... there's a very small rounding error in the calculations which gets discarded when rounding to a less precise format. This is also the reason for keeping internal calculation at higher precision than the representation in memory)

--EDIT--
And, like Sneftel said, round instead of cast.
It looks like you're right. When I do:

long double somedouble = log(8)/log(2);
cout << int(somedouble) << endl;

It produces the incorrect 2.

Quote:Original post by c2_0
Internally it would be using extended precision (80bits - long double).

When you assign to the double, that internal result will get rounded to 3.

So, I'll correct myself. It would be the conversion from the extended precision to either double or float which rounds to 3, not the conversion from double to float (although, the principle is the same ... there's a very small rounding error in the calculations which gets discarded when rounding to a less precise format. This is also the reason for keeping internal calculation at higher precision than the representation in memory)

--EDIT--
And, like Sneftel said, round instead of cast.


Mike C.http://www.coolgroups.com/zoomer/http://www.coolgroups.com/ez/

This topic is closed to new replies.

Advertisement