Reputation: 3314
I have a list of double values, I want to Round a variable's value to only that list of numbers
Example:
The list contents are: {12,15,23,94,35,48}
The Variable's value is 17, So it will be rounded to 15
If The variable's value is less than the least number, it will be rounded to it, if it's value is larger than the largest number, it will be rounded to it.
The list contents is always changing according to an external factor, So I cannot hardocde the values I Want to round up or down to.
How can do it in C# ?
Upvotes: 10
Views: 2987
Reputation: 1
Simple rounding down in linq
public decimal? RoundDownToList(decimal input, decimal[] list)
{
var result = (from number in list
where number <= input
orderby number descending
select number).FirstOrDefault();
return result;
}
Upvotes: 0
Reputation: 50858
Assuming the array is sorted, you could perform a binary search in the array, narrowing it down to which two numbers the given number lies between.
Then once you have these two numbers, you simply round to the nearest of the two.
static int RoundToArray(int value, int[] array) {
int min = 0;
if (array[min] >= value) return array[min];
int max = array.Length - 1;
if (array[max] <= value) return array[max];
while (max - min > 1) {
int mid = (max + min) / 2;
if (array[mid] == value) {
return array[mid];
} else if (array[mid] < value) {
min = mid;
} else {
max = mid;
}
}
if (array[max] - value <= value - array[min]) {
return array[max];
} else {
return array[min];
}
}
Upvotes: 6
Reputation: 50835
Here's a method using LINQ:
var list = new[] { 12, 15, 23, 94, 35, 48 };
var input = 17;
var diffList = from number in list
select new {
number,
difference = Math.Abs(number - input)
};
var result = (from diffItem in diffList
orderby diffItem.difference
select diffItem).First().number;
EDIT: Renamed some of the variables so the code is less confusing...
EDIT:
The list
variable is an implicitly declare array of int
. The first LINQ statement diffList
defines an anonymous type that has your original number from the list (number
) as well as the difference between it and your current value (input
).
The second LINQ statement result
orders that anonymous type collection by the difference, which is your "rounding" requirement. It takes the first item in that list as it will have the smallest difference, and then selects only the original .number
from the anonymous type.
Upvotes: 13
Reputation: 6425
Do something like this:
double distance = double.PositiveInfinity;
float roundedValue = float.NaN;
foreach (float f in list)
{
double d = Math.Abs(d - f);
if (d < distance)
{
distance = d;
roundedValue = f;
}
}
Upvotes: 1
Reputation: 740
You could loop through the array of numbers and set a roundedNum variable equal to each one if a variable delta is less than the current lowest delta. Some things are best described in code.
int roundedNum = myNum;
int delta = myArray[myArray.Length-1] + 1;
for(int i=0; i<myArray.Length; ++i) {
if(Math.Abs(myNum - myArray[i]) < delta) {
delta = Math.Abs(myNum - myArray[i]);
roundedNum = myArray[i];
}
}
That should do the trick quite nicely.
Upvotes: 1
Reputation: 69260
Using linq:
int value = 17;
var values = new float[] { 12, 15, 23, 94, 35, 48 };
if(value < values.First()) return value.First();
if(value > values.Last()) return value.Last();
float below = values.Where(v => v <= value).Max();
float above = values.Where(v => v >= value).Min();
if(value - below < above - value)
return below;
else
return above;
As long as then number of possible values is quite small this should work. If you have thousands of possible values another solution should be used, which takes advantage of values
being sorted (if it really is sorted).
Upvotes: 2