2011-04-26 60 views
9

所以我只想查找給定數字的所有除數(除了數字本身)。 目前,我有這樣的:高效查找數字的所有因數

public static List<int> proper_divisors(int x) 
{ 
    List<int> toreturn = new List<int>(); 
    toreturn.Add(1); 
    int i = 0; 
    int j=1; 
    int z = 0; 
    while (primes.ElementAt(i) < Math.Sqrt(x)) 
    { 
     if (x % primes.ElementAt(i) == 0) 
     { 
      toreturn.Add(primes.ElementAt(i)); 
      toreturn.Add(x/primes.ElementAt(i)); 
      j = 2; 
      z = (int)Math.Pow(primes.ElementAt(i), 2); 
      while (z < x) 
      { 
       if (x % z == 0) 
       { 
        toreturn.Add(z); 
        toreturn.Add(x/z); 
        j++; 
        z = (int)Math.Pow(primes.ElementAt(i), j); 
       } 
       else 
       { 
        z = x; 
       } 
      } 
     } 
     i++; 
    } 
    toreturn = toreturn.Distinct().ToList<int>(); 
    return toreturn; 
} 

其中素數是素數的列表,(假設它是正確的,足夠大)。 該算法的工作原理是它可以找到所有的素數因子,但不是所有的因子(即給出34534,它返回{1,2,17267,31,1114}但錯過{62,557},因爲62是一個組合,因此錯過557爲好。

我也嘗試剛開了許多的首要因素,但我不知道如何將其轉換成所有的正確組合的列表。

的該算法的代碼如下:

public static List<int> prime_factors(int x) 
{ 
    List<int> toreturn = new List<int>(); 
    int i = 0; 
    while (primes.ElementAt(i) <= x) 
    { 
     if (x % primes.ElementAt(i) == 0) 
     { 
      toreturn.Add(primes.ElementAt(i)); 
      x = x/primes.ElementAt(i); 
     } 
     else 
     { 
      i++; 
     } 
    } 
    return toreturn; 
} 

關於如何解決的第一個,或如何創建組合從塞康列表中的任何想法d一個(我寧願那樣會更快)?

+0

的可能的複製[最佳在C#中查找給定數字的所有因素的方法](http://stackoverflow.com/questions/239865/best-way-to-find-all-factors-of-a-given-number-in-c-sharp ) – MxNx 2016-10-03 11:53:49

回答

7

既然你已經擁有的主要因素清單,你想要做的是計算該列表的冪。

現在,一個問題是,你可能會在列表中重複(例如20 = 2 * 2 * 5的主要因素),但集合不允許重複。因此,我們可以通過將其投影到形式爲{x,y}的結構來使列表中的每個元素唯一,其中x是素數,y是列表中素數的索引。現在

var all_primes = primes.Select((x, y) => new { x, y }).ToList(); 

all_primes的形式是{X,Y},其中x是素數,y是該列表中的索引的列表。

然後我們計算功率設定(以下GetPowerSet定義):

var power_set_primes = GetPowerSet(all_primes); 

因此,power_set_primesIEnumerable<IEnumerable<T>>其中T是匿名類型{x, y}其中x和y是int類型。

接下來,我們計算的權力每個元素的產品集

foreach (var p in power_set_primes) 
{ 
    var factor = p.Select(x => x.x).Aggregate(1, (x, y) => x * y); 
    factors.Add(factor); 
} 

全部放在一起:

var all_primes = primes.Select((x, y) => new { x, y }).ToList(); //assuming that primes contains duplicates. 
var power_set_primes = GetPowerSet(all_primes); 
var factors = new HashSet<int>(); 

foreach (var p in power_set_primes) 
{ 
    var factor = p.Select(x => x.x).Aggregate(1, (x, y) => x * y); 
    factors.Add(factor); 
} 

http://rosettacode.org/wiki/Power_Set爲冪的實現。

public IEnumerable<IEnumerable<T>> GetPowerSet<T>(List<T> list) 
{ 
    return from m in Enumerable.Range(0, 1 << list.Count) 
      select 
       from i in Enumerable.Range(0, list.Count) 
       where (m & (1 << i)) != 0 
       select list[i]; 
} 
+0

我不關注。因素是我發現的主要因素列表? 因爲我想要的是乘以小於或等於數字的因素的所有組合,必須有更好的方法。 – soandos 2011-04-26 16:48:51

+0

Opps,那不應該是Math.Floor ...編輯... – 2011-04-26 16:52:05

+0

雖然這不是真的。目前,如果素數超過自身時間,這將不會給出正確的因素(這種情況發生了很多,即每次9是一個因素......) – soandos 2011-04-26 16:59:45

5

有類似的問題before,它有一個使用IEnumerable的有趣解決方案。如果你想要所有的因數而不是因素,並且假設你至少使用C#3。0您可以使用這樣的事情:

static IEnumerable<int> GetDivisors(int n) 
{ 
    return from a in Enumerable.Range(2, n/2) 
      where n % a == 0 
      select a;      
} 

,然後用它是這樣的:

foreach(var divisor in GetDivisors(10)) 
    Console.WriteLine(divisor); 

,或者,如果你想有一個列表,只需:

List<int> divisors = GetDivisors(10).ToList(); 
+0

再次,這是一個很好的方式來做它的蠻力。但鑑於我有一個必要的素數列表,沒有理由這樣做。 – soandos 2011-04-26 16:46:33

+0

因此,如果你有數字的所有主要因素,並且只想要它們之間的所有組合,爲什麼不使用笛卡爾積,那就是:'從素數中的y在素數中選擇x!= y選擇x * y' ?這可以解決你的問題,只要你的素數有1(否則.Concat(素數)就可以解決這個問題) – LazyOfT 2011-04-26 16:59:21

+0

我該怎麼做? – soandos 2011-04-26 17:00:15