Convert decimal to int with ceil and floor - C++

Started by
11 comments, last by JohnBolton 16 years, 9 months ago
Hi, I'm having a little problem of converting a decimal value to an int and either ceil it or floor it depending if the value is above .5 or not. In C#, this is done automatically, in C++, it seems like it will floor down the value all the time. Example code: const double a = 0.496241; const double b = -5.214286; int mod = ((a * 18) + b); // results in 3.7, so i want it ceiled to 4 and not floored to 3. If I need to manually check if the decimal value is equal or less to .5 to either ceil or floor, how do I get my hands on the decimal value in a simple manner?
Advertisement
Quote:Original post by Nunyah
const double a = 0.496241;
const double b = -5.214286;
int mod = ((a * 18) + b); // results in 3.7, so i want it ceiled to 4 and not floored to 3.
Just add 0.5 before truncating to an int. E.g:
int mod = ((a * 18) + b + 0.5);
That's a very neat solution, had I not depended on negative results.
I guess my example should have mentioned that, sorry. The value of 18, can be anything from 1 and upwards.

So if the number is 8 or 9, I should end up with -1, 6 or 7 would be -2 and so on.

Example code:
int Person::CalcModifiers(int stat)
{
/* Based on linear regression. 6 and 7 = -2, 8 and 9 = -1, 10 and 11 = 0, 12 and 13 = 1 etc 18 and 19 = 4 */
const double a = 0.496241;
const double b = -5.214286;
return int((a * stat) + b);
}
this probably is not the best solution but i guess it works:
float fmod;
int mod = fmod = ((a * 18) + b);


now calculate the difference between them if it's bigger than 0.5 just add 1 to the int or substract one if you are working with negative numbers.

in case of the example: 3.7-3=0.7 which is bigger than 0.5, so 3+=1 gives 4! :)
The following code solved my question. Probably a real kludge, so please improve with cleaner code! :)

int Person::CalcModifiers(int stat)
{
/* Based on linear regression. 7 = -2, 8 and 9 = -1, 10 and 11 = 0, 12 and 13 = 1 etc 18 and 19 = 4 */
const double a = 0.496241;
const double b = -5.214286;
double mod = ((a * stat) + b);
double dec = mod - int(mod);

if (dec < 0.5 && dec > 0)
{
return floor(mod);
}
else if(dec >= 0.5)
{
return ceil(mod);
}
else if(dec < -0.5)
{
return floor(mod);
}
else
{
return ceil(mod);
}
}
How about:

int round( double x )
{
return int( x + 0.5 * sign(x) );
}
How about this?
int round(double x){return int(x > 0.0 ? x + 0.5 : x - 0.5);}


(stolen from here)

C++: A Dialog | C++0x Features: Part1 (lambdas, auto, static_assert) , Part 2 (rvalue references) , Part 3 (decltype) | Write Games | Fix Your Timestep!

That is indeed a lot cleaner and less error prone. Thank you, guys!
If what you're really trying to do is create the mapping "6 and 7 = -2, 8 and 9 = -1, 10 and 11 = 0, 12 and 13 = 1 etc 18 and 19 = 4", then all this linear regression and rounding stuff is much too complicated. :)

Instead, *use* the behaviour of integer division in C++: if you divide those input values by 2, then the mapping becomes "3 and 3 = -2, 4 and 4 = -1, 5 and 5 = 0, etc.", and it's bleedingly obvious what to do:

int Person::CalcModifier(int stat) {  // Just a point on function naming: I changed it to be singular, to reflect the  // fact that only one modifier is being calculated.  return (stat / 2) - 5;}


If you need to handle negative inputs (which I doubt - it looks like this is for implementing some D20 system stuff, yes? :) ), things are slightly complicated, because C and C++ don't specify the rounding direction when you divide a negative value. (This is in the long established but far from fine :) tradition of leaving these kinds of things undefined so that the compiler can pick out the fastest possible translation to machine code.) But it's easily dealt with when you want to round towards zero: simply detect the sign, flip the value if it's negative, do the math, and restore the sign. When you want to be sure of rounding towards minus infinity, it's a little trickier, but still doable :)
You're right, linear regression is a lot more complicated than it has to, seeing your piece of code, thanks!

And yes, it's a D20 system for my C++ Workshop project, although a bit late. :)

This topic is closed to new replies.

Advertisement