Mapping uint to value within min/max set I have a method that transforms any input uint into a [min,max] set. I am looking for improvements on the function, specifically to get rid of the input == uint.MaxValue case.

public static uint NumberInRange(uint input, uint min, uint max)
{
    decimal divider = uint.MaxValue / (decimal)max;
    if (input == uint.MaxValue)
        return (uint)max;

    var i = (uint)(Math.Floor(input / divider) + min);
    return i;
}


Let me know if you see any ways to improve this function, or if you think that there is any subtle bug within it.

I am basically just looking into a way to map a bigger set [0,uint.MaxValue] into a smaller set [min,map].

Let's say the inputs are:

NumberInRange(0, 10, 100) - I should get 10

NumberInRange(uint.MaxValue, 10, 100) - I should get 100

For any number in between, I want them to be mapped "equally" between members of the set.

Let's say I put in a number that gives value between 0 and 1:

for (input / (uint.MaxValue/max)))


All 0.xxxx values should map to min (instead of getting min for numbers between 0 and 0.5, and min+1 for 0.5-1.5, etc) in order to see equal distribution in mapping (hence Math.Floor).

I think the function does it's job pretty well.  I was just looking to see if I can eliminate that if (input == uint.MaxValue) case since it's a weird edge case (for which result is max+1). This is also one thing that can be nitpicked from math standpoint - all members of the set will get mapped from n elements, while the last member will get mapped from n+1 elements (because of this special if case).
I would recommend considering this using more explicitly the Two-Point Equation of a Line. Your code is basically doing the same thing, but thinking more explicitly in terms of the underlying mathematics would help avoid errors or extra complication.

Here is how I would implement this:


public static uint LinearTransform(uint x, uint x1, uint y1, uint x2, uint y2) {
    ulong a = (ulong)(y2 - y1)*(x - x1);
    uint b = (x2 - x1);
    return (uint)(a/b) + (a%b*2 >= b)?1:0 + y2;
}


I don't actually know C#, so it is likely that the code is not syntactically correct, or breaks the style rules of the language, but it should get the point across.

The (a%b*2 &gt;= b)?1:0 term is to compensate for the way integer division always truncates to zero. This will make it instead round up if the fractional part would be 1/2 or more, so we don't need to do any floating point computations.

This function can then be used to perform your original task by calling it as LinearTransform(input, 0, min, uint.MaxValue, max).