Sign in to follow this  

Rounding Floating Point Values

This topic is 4857 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I need a function that mimicks excel's ROUNDUP function. Basically the ROUNDUP function is described like this: It rounds a value away from zero with two given parameters. Parameter 1 is the number to round, and parameter 2 is the digit to round to. If the rounding digit is 0 it rounds to the nearest whole number, and negative numbers round to the left of the decimal point. For example: ROUNDUP(5.5, 0) = 6 ROUNDUP(-5.5, 0) = -6 ROUNDUP(55, -1) = 60 ROUNDUP(3.14159, 1) = 3.1 Is there any C function that supplies this sort of functionality? I've been writing my own but it is very tedious and somewhat exausting. Thanks

Share this post


Link to post
Share on other sites
You can use ceil to round up and use some dividing/multiplying by 10 to round to decimal places. You'd still have to write your own, but it'll probably be easier than whatever you're writing now (unless that's actually what you're doing).

For instance, float x = ceil(55f / 10f) * 10f; would round 55 to 60.

That better, hplus0603? [wink]

Share this post


Link to post
Share on other sites
I was bored and was up for a bit of a challenge. Five minutes later this seems to do what you intend it to.. tell me if it doesn't work as you expected.


float roundup(float Num, int Places)
{

float mod = pow(10,places);
if (Places > 0)
Num *= mod;
if (Places < 0)
Num /= mod;

if (Num > 0)
Num += 0.5f;
else
Num -= 0.5f;

Num = (float) int(Num);

if (Places > 0)
Num /= mod;
if (Places < 0)
Num *= mod;


return Num;
}




EDIT: Did a quick fix on the code.. silly me for not noticing that.

[Edited by - falkone on August 27, 2004 11:48:01 AM]

Share this post


Link to post
Share on other sites
Your code won't work. Besides the inefficient float/int conversion, test your code when Places is 2. It won't work. This will work in all cases:

float RoundUp ( float Num, float Places )
{
float Shift = powf(10, Places);
Num *= Shift;
if( Num < 0 )
Num = -ceilf(-Num);
else
Num = ceilf(Num);
Num /= Shift;
return Num;
}


Share this post


Link to post
Share on other sites
Yah bro if you want to do the base 10 deal it needs to be exponential. I wrote up something that looks like this and it does what I want:

[SOURCE]
float roundf(const float fValue, const int iDigit) {
if(iDigit==0) {
if((float)(int)fValue==fValue) {
return fValue;
}
float fRetVal = (float)(int)fValue;
if(fValue>0.0) {
fRetVal+=1.0f;
}
else if(fValue<0.0) {
fRetVal-=1.0f;
}
return fRetVal;
}
else if(iDigit < 0) {
float fTemp = (float)pow(10.0, (double)(-1*iDigit));
float fScaledValue = fValue / fTemp;
if((float)(int)fScaledValue*fTemp==fValue) {
return fValue;
}
else {
if(fScaledValue<0) {
fScaledValue = (float)(int)fScaledValue;
fScaledValue-=1.0f;
fScaledValue*=fTemp;
}
else {
fScaledValue = (float)(int)fScaledValue;
fScaledValue+=1.0f;
fScaledValue*=fTemp;
}
return fScaledValue;
}
}
else {
float fTemp = (float)pow(10.0, (double)(iDigit));
float fScaledValue = fValue * fTemp;
if((float)(int)fScaledValue/fTemp==fValue) {
return fValue;
}
else {
if(fScaledValue<0) {
fScaledValue = (float)(int)fScaledValue;
fScaledValue-=1.0f;
fScaledValue/=fTemp;
}
else {
fScaledValue = (float)(int)fScaledValue;
fScaledValue+=1.0f;
fScaledValue/=fTemp;
}
return fScaledValue;
}
}
}
[/SOURCE]


The only catch is that sometimes I get added crap on the end (I blame the fpu) and it does a really poor job of doing floats past the 4th digit to the right of the decimal. Can anybody verify that this works? What concerns me is when I pass it:
-911.12345 with 1 as the digit I get -911.200012 instead of -911.200012, and I think this problem manifests itself more strongly when I do digits like 5 and 4. Thanks.

Share this post


Link to post
Share on other sites
That code is much slower and more complicated than it needs to be. You'll find mine works in all cases. I did a test run with your number and these are the results:

RoundUp(-911.12345f, 1) prints "-911.200000"
RoundUp(-911.12345f, 4) prints "-911.123500"
RoundUp(-911.12345f, -2) prints "-1000.000022"

That 22 at the end is a result of 32-bit floating-point imprecision.

Share this post


Link to post
Share on other sites
Ok your code and my code are effected by the same inaccuracy (which really sucks). I tried converting your code to using doubles and then casting to a float and the same inaccuracy exists. But yah, my implementation was way more complicated then it needed to be. Thanks for your help.

Share this post


Link to post
Share on other sites
Quote:
Original post by 31337
I tried converting your code to using doubles and then casting to a float and the same inaccuracy exists.

Yeah, even directly assigning a number to a float can still show precision errors. In Visual C++, if you say "float var = 0.1" it'll generate a warning for converting a double to a float. This is because 0.1 cannot be stored exactly in floating-point format, but a double would at least be more accurate than a float. It's like storing 1/7 in decimal format, which is 0.1428571428... infinite digits. You can't represent the exact number.

Share this post


Link to post
Share on other sites

This topic is 4857 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this