views:

693

answers:

4

What is a good algorithm to determine the necessary fraction needed to add/sub to the number in order to round it to the nearest integer without using the inbuilt ceiling or floor funcitons?

Edit: Looking for a mathematical number trick to figure out the part needed to round the number to the nearest integer. The more primitive the math operations the better. Please avoid using other's procedures. 0.5 can be taken eitherway, whatever suits your method. This is NOT my homework question, nor am I going to use this anywhere.

+4  A: 

Mod the number with one to get the decimal part, if its >0.5, round up, else round down

OR

Divide the number by 0.5, if its odd, round up, else round down

Simonw
Note that some languages only define mod/% on integers.
Stephan202
The algorithm is clever if x %1 >= 0.5 print ((x- x%1) + 1) -xelse print x%1endCan you please think of anothersolution without the %?
kunjaan
Any other constraints? will dividing do the trick?
Simonw
I dont think dividing by 0.5(multiplying by 2) will work.
kunjaan
Why?Without any other info its impossible to answer this question
Simonw
what further info do you need? I was thinking in the same line. There has to be a neat mathematical procedure to solve this question. There arent any other constraints. Just figure out the part needed to round the number to the nearest integer. The more primitive the math operations the better.
kunjaan
Why does multiplying by two not work? If you want more primitive operations, add the number to itself
Simonw
A: 

Can you explain why you want/need such an algorithm?

VVS
Could it be homework? Seems like an unrealistic scenario to me...
spender
This is not a homework question. Just fiddling around with floors and ceilings.
kunjaan
+3  A: 

If you can't use mod (because it might only be defined for integers in your language, you might be able to do something like this (in C-ish pseudocode):

// make the input positive:
boolean inputPositive = true;
if (input < 0) {
  input = 0 - input;
  inputPositive = false;
}

// subtract 1 until you just have the decimal portion:
int integerPart = 0;
while (input > 1) {
  input = input - 1;
  integerPart++;
}

int ret;
if (input >= 0.5) { // round up
  ret = integerPart + 1;
} else {
  ret = integerPart;
}

if (inputPositive) {
  return ret;
} else {
  return 0 - ret;
}

This solution doesn't use mod or any outside functions. Of course, I can't imagine why you would want this in real life. It is interesting to think about, though.

pkaeding
Very good answer according to me it follows all the requirements! :-)
yves Baumes
+1 of course, I forgot to mention .. ;-)
yves Baumes
+1. You could improve on this by subtracting ever smaller powers of two, so that this procedure will also terminate within reasonable time for large inputs.
Stephan202
This is very interesting. I like the part where you check if the number is positive. I hadnt thought about that. I had hoped somebody would come with math tricks and even though subtracting one is quite tedious, i think this solution works. Thanks.
kunjaan
+2  A: 

Once you have the fractional part of the number, the problem is pretty much solved. One way to get the fractional part is to repeatedly subtract powers-of-2 from you number (assuming it has been made positive, if it were negative to begin with).

The function below, getWholeMaker, returns what you want (the "thing" that must be added to round the number). It's running time is O(log(n)), and uses only elementary operations.

/* Returns the factional part of x */
double getFrac(double x) {
    if(x < 0) x = -x;
    if(x < 1) return x;
    else if(x < 2) return x-1;

    /* x >= 0 */
    double t = 2;
    while(t+t <= x) t += t;
    /* t is now the largest power of 2 less than or equal to x */
    while(t >= 1) {
        if(t <= x) x -= t;
        t /= 2;
    }

    return x;
}

double getWholeMaker(double x) {
    double frac = getFrac(x);
    double sign = x >= 0 ? +1 : -1;
    return sign * (frac <= 0.5 ? -frac : 1-frac);
}
Ashutosh Mehra
Sweet. But this looks like pkaeding's algorithm optimized. Am i correct?
kunjaan
Yes, It's like pkaeding's, but works in logarithmic time (pkaeding's is linear time).
Ashutosh Mehra