Question

double d = 0; // random decimal value with it's integral part within the range of Int32 and always positive.
int floored = (int) Math.Floor(d); // Less than or equal to.
int ceiled  = (int) Math.Ceiling(d); // Greater than or equal to.
int lessThan = ? // Less than.
int moreThan = ? // Greater than.

The Floor and ceiling functions include the largest/smallest integer that is less than/greater than or equal to d respectively. I want to find out the largest/smallest integer that is less than/greater than but NOT equal to d respectively.

OF course this can be achieved through a few if's and but's but I am looking for a method that either does not include branching or is at least a very fast since this operation will be performed billions of times in an algorithm.

Is binary manipulation possible? If not, what would be the best alternative?

The obvious solution would be something like:

int lessThan = (d - floored) > double.Epsilon ? floored : (floored-1);
int moreThan = (ceiled - d) > double.Epsilon ? ceiled : (ceiled+1);

NOTE: The objective is to find out whether d is closer to lessThan or moreThan.

Was it helpful?

Solution

Since d is always positive, you can use that casting to an integer truncates (ie it's the floor for positive input and the ceiling for negative input).

floor(d + 1) is the same as ceil(d) + 1 if integer, ceil(d) otherwise and ceil(d - 1) is the same as floor(d) - 1 if integer, floor(d) otherwise

int moreThan = (int)(d + 1); // floor(d + 1)
int lessThan = int.MaxValue + (int)((d - int.MaxValue) - 1) // ceil(d - 1)

The lessThan is somewhat convoluted, I wouldn't be surprised if someone else has a better idea.

But since you want this:

The objective is to find out whether d is closer to lessThan or moreThan

It should be even simpler:

double x = d % 1;
if (x == 0 || x == 0.5)
    // d is equally far from either one, either by a difference of 1 or of 0.5
else if (x < 0.5)
    // d is closer to lessThan
else
    // d is closer to moreThan

OTHER TIPS

I can missunderstand question, but to find nearest integer value of d:

int floored = (int)d;
int ceiled = (int)(d + 1);
int mathRounded = (int)(d + 0.5)

Haven't perf tested this but you could test to see if your double is an integer already and then perform the appropriate operation:

double d = 0;
int lessThan;
int moreThan;

if (d % 1 == 0)
{
    lessThan = d - 1;
    moreThan = d + 1;
}
else
{
    lessThan = (int) Math.Floor(d);
    moreThan  = (int) Math.Ceiling(d);
}

I don't know what results you want to achieve at the end.

If you want the ceil, floor and what is the closest:

int lessThan = (int) Math.Floor(d); // Less than or equal to.
int moreThan = (int) Math.Ceiling(d); // Greater than or equal to.

// 1 comparison instead of 2 that is made on your question.
if (lessThan == moreThan)
{
    lessThan--;
    moreThan++;
 }

 bool isCloserToFloor = (d - .5) < lessThan;
 bool isCloserToCeil = !isCloserToFloor;

You can cheat a bit: use Convert.ToInt32(bool):

double d = 0; // random decimal value with it's integral part within the range of Int32 and always positive.
int floored = (int) Math.Floor(d); // Less than or equal to.
int ceiled  = (int) Math.Ceiling(d); // Greater than or equal to.
int lessThan = floored - Convert.ToInt32(Math.Abs(d-floored) < epsilon);
int moreThan = ceiled + Convert.ToInt32(Math.Abs(d-ceiled) < epsilon);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top