patterncsharpMinor
Mapping uint to value within min/max set
Viewed 0 times
uintvaluewithinminmaxmappingset
Problem
I have a method that transforms any input
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
Let's say the inputs are:
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:
All 0.xxxx values should map to
I think the function does it's job pretty well. I was just looking to see if I can eliminate that
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 10NumberInRange(uint.MaxValue, 10, 100) - I should get 100For 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).Solution
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
This function can then be used to perform your original task by calling it as
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 >= 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).Context
StackExchange Code Review Q#55607, answer score: 3
Revisions (0)
No revisions yet.