开发者

Returning the nearest multiple value of a number

I need a function by which I will be able to convert a number to a nearest value of a given 开发者_C百科multiple.

Eg i want an array of number to be set to the neareast multiple of 16, so 2 = 0, 5 = 0, 11 = 16, 17 = 16, 30 = 32 etc

thanks


Some division and rounding should be all you need for this:

int value = 30;
int factor = 16;
int nearestMultiple = 
        (int)Math.Round(
             (value / (double)factor),
             MidpointRounding.AwayFromZero
         ) * factor;

Be careful using this technique. The Math.Round(double) overload believes the evil mutant MidpointRounding.ToEven is the best default behavior, even though what we all learned before in school is what the CLR calls MidpointRounding.AwayFromZero. For example:

var x = Math.Round(1.5); // x is 2.0, like you'd expect
x = Math.Round(0.5); // x is 0. WAT?!


You don't need to do any floating point division, it's unnecessary. Use the remainder operator:

int rem = val % multiple;
int result = val - rem;
if (rem >= (multiple / 2))
    result += multiple;


16*((n+8)/16) is the formula you want if, in particular, you want to convert 8 to 16 (it's equally close to 0 as to 16, so it's impossible to decide how to convert it based exclusively on the "nearest multiple" concept, you have to decide!-), and of course consistently 24 to 32, 40 to 48, and so forth. Use +7 in lieu of +8 if you'd rather convert 8 to 0 rather than to 16 (and consistently 24 to 16, and so forth).

To use a generic X in lieu of the hardcoded 16, then the formula is X*((n+X/2)/X) (with the same proviso as in the above paragraph if X is even).

Edit: no need to mess around with floating point numbers as other answers suggest, but you do need to multiply back by X (which I had erroneously omitted).


In case of rounding of to the nearest multiple of a float, you can use this:

public static float convert(float value, float multipleOf) 
{
    return (float) Math.Round((decimal)value / (decimal)multipleOf, MidpointRounding.AwayFromZero) * multipleOf;
}

Then you can use the function like this:

Console.WriteLine("Convert 10.723: " + convert(10.723f, 0.5f)); // 10.5


The case is a bit more complicated if the multiple is less than 1. I wrote this general function:

public float NearestRound(float x, float delX)
{
    if (delX < 1)
    {
        float i = (float)Math.Floor(x);
        float x2 = i;
        while ((x2 += delX) < x) ;
        float x1 = x2 - delX;
        return (Math.Abs(x - x1) < Math.Abs(x - x2)) ? x1 : x2;
    }
    else {
        return (float)Math.Round(x / delX, MidpointRounding.AwayFromZero) * delX;
    }
}

/* Sample:
x: 101 multiple:2 NearestRound -> 102
x: 107 multiple:2 NearestRound -> 108
x: 100.9 multiple:2 NearestRound -> 100
x: 1 multiple:0.25 NearestRound -> 1
x: 1.35 multiple:0.25 NearestRound -> 1.25
x: 1.77 multiple:0.25 NearestRound -> 1.75
x: 1.9 multiple:0.25 NearestRound -> 2 */


Rounds the middle towards +∞

int RoundNearest16(int value)
{
    return (value + 8) & ~0xF;
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜