2011-10-23 13 views
6

我有雙值的列表,我想一個變量的值四捨五入到只有號碼列表四捨五入的值僅在C#中的某些值的列表

例子:

列表內容:{12,15,23,94,35,48}

變量的值是17,因此,這將被舍入到15

如果變量的值小於數量最少,這將被舍入對它來說,如果它的價值大於最大數量,它將被四捨五入。

列表內容總是根據外部因素而變化,所以我不能強迫我想要舍入或捨棄的值。

在C#中如何做到這一點?

+0

你可以使用LINQ嗎? – Yuck

+0

計算未包含值與可能結果之間的差異。將這些差異存儲在可能結果鍵入的字典中,並選擇差異最小的結果。 – Keyo

+2

這個系列有多大?否則,您應該考慮使用已排序的集合並使用二分搜索。 –

回答

8

下面是使用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; 

編輯:重命名一些變量,從而降低了代碼的混亂...

編輯

list變量是隱式聲明的int數組。第一條LINQ語句diffList定義了一個匿名類型,它包含列表中的原始數字(number)以及它與當前值(input)之間的差異。

第二條LINQ語句result命令那個匿名類型集合的區別,這是你的「四捨五入」的要求。它取得該列表中的第一個項目,因爲它將具有最小的差異,然後從匿名類型中僅選擇原始的.number

+0

+1。它比我的解決方案更有效率,因爲它只循環一次'values'。 –

+0

作品像一個魅力,雖然我無法理解它:) – SKandeel

+0

非常感謝您的解釋... – SKandeel

7

假設數組排序爲,您可以在數組中執行binary search,將其縮小到給定數字之間的兩個數字。

然後,一旦你有這兩個數字,你只需繞到最近的兩個。

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]; 
    } 

} 
+0

不僅假設,如果這應該在大集合上工作,排序集合是要走的路。 –

+3

實際上當然沒關係,但我注意到你正在做兩個整數中點的「危險」方法。如果min + max恰好溢出到負數,那麼一半是負數。請參閱這篇文章,以獲得對該問題及其可能解決方案的有趣分析:http://locklessinc.com/articles/binary_search/ –

1

使用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; 

只要那麼可能值的數量很少這應該工作。如果您有數千個可能的值,則應該使用另一個解決方案,該方案利用values進行排序(如果確實排序)。

+0

錯誤'int'不包含'First'和'沒有擴展方法'的定義First '可以找到'int'類型的第一個參數(你是否缺少using指令或程序集引用?) – SKandeel

1

你可以通過循環數的陣列,並設置一個roundedNum變量等於每一個如果可變增量是小於當前最低增量。有些東西最好用代碼描述。

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]; 
    } 
} 

這應該很好地做到這一點。

2

做這樣的事情:

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; 
    } 
}