2

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.

unj2
  • 52,135
  • 87
  • 247
  • 375

3 Answers3

4

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
  • 852
  • 4
  • 12
  • 29
  • 1
    Note that some languages only define mod/% on integers. – Stephan202 May 17 '09 at 19:13
  • The algorithm is clever if x %1 >= 0.5 print ((x- x%1) + 1) -x else print x%1 end Can you please think of anothersolution without the %? – unj2 May 17 '09 at 19:17
  • Why? Without any other info its impossible to answer this question – Simonw May 17 '09 at 19:34
  • 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. – unj2 May 17 '09 at 19:38
  • Why does multiplying by two not work? If you want more primitive operations, add the number to itself – Simonw May 17 '09 at 19:41
3

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.

Svante
  • 50,694
  • 11
  • 78
  • 122
pkaeding
  • 36,513
  • 30
  • 103
  • 141
  • 1
    Very good answer according to me it follows all the requirements! :-) – yves Baumes May 17 '09 at 19:40
  • 1
    +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 May 17 '09 at 19:45
  • 1
    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. – unj2 May 17 '09 at 19:48
3

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
  • 2,582
  • 1
  • 19
  • 15