2011-07-04 16 views
6

与えられた数字が完全な数であるかどうかを見つけるアルゴリズムを探しています。数字が完全な数字であるかどうかをチェックするアルゴリズム

私の心に来るという最もシンプルである:

  1. は数
  2. のすべての要因が[それが素数である場合、番号自体を除い]素因数を取得し、それらを合計して下さいそれが完全な数であるかどうかを確認してください。

これを行うより良い方法はありますか? 検索すると、ユークリッドの仕事が始まりましたが、良いアルゴリズムは見つかりませんでした。また、このgolfscriptは役に立たなかった:https://stackoverflow.com/questions/3472534/checking-whether-a-number-is-mathematically-a-perfect-number。など

番号が
しかし、これは面接で聞かれていることから、[私は完璧な番号が:)を使用しているところを知らない]現実世界の使用中などをキャッシュすることができ、私が想定しています「導出」があるべきそれを最適化する方法。

ありがとうございます!

+1

あなたのステップ#2では、_prime_要因の合計ではなく、その要因の合計ではありません。例えば。 1 + 2 + 4 + 7 + 14 = 28(4因子と14因子に注意)のため、28は完璧です。 – mjv

+0

thnx、私はそれを修正しました。 – codeObserver

答えて

9

入力が偶数の場合は、2^(p-1)*(2^p-1)の形式であり、p2^p-1がプライムであるかどうかを確認してください。

入力が奇数の場合は "false"を返します。 :-)

詳細はWikipedia pageを参照してください。

(実際には、2500万桁未満の完全な数字が47個しかないので、それらの単純な表から始めることができます)64ビットの数字を使用していると仮定できるかどうか面接者に問い合せます。 )

+5

このようなインタビューの質問の両端にいるので、テーブルのようなものを期待しているのでしょうか?回答。それは非常に特定の知識を求めているようです。私は数学を知っている人ではなく、プログラムできる人がほしいと思う。 – andrewdski

+1

メルセンヌ数(2^p)-1の素数については、特殊な[Lucas-Lehmer検定](http://en.wikipedia.org/wiki/Lucas%E2%80%93Lehmer_primality_test)に注意してください。 – hardmath

+0

リンクのthnx私は派生可能な最適化はないと思う。テーブルを使用していない場合、おそらくインタビュアーは計算を使用できるプログラマー以上のコードを書くことができる数学者が必要だろう! – codeObserver

0

これは簡単なアルゴリズムです(PHPの場合は単純なforループを使用してください)。簡単に他の言語に移植することができます:

function isPerfectNumber($num) { 
     $out = false; 

     if($num%2 == 0) { 
      $divisors = array(1); 
      for($i=2; $i<$num; $i++) { 
       if($num%$i == 0) 
        $divisors[] = $i; 
      } 

      if(array_sum($divisors) == $num) 
       $out = true; 
     } 

     return $out ? 'It\'s perfect!' : 'Not a perfect number.'; 
    } 

これはあなたが探しているものかどうかわかりません。

+0

機能的には正しいですが、この実装は最適ではありませんが、主な欠点は、その動作範囲が完璧な数値/メルセンの世界ではかなり小さい数であるPHP整数に縛られていることです;-) GMP(任意の長さの整数)、2^PHP_INT_SIZEの制限を越えたい場合。 – mjv

+0

thnx、私はこれを行うより速い方法を探していた。大きい数字のためにそれを得ることは遅いでしょうか? – codeObserver

+0

除数を保存して後で追加するよりも、除数を見つけた直後に追加する方が理にかなっていませんか?また、2から始めると、if条件が '$ sum + 1 == $ num'でないはずです。 – rath

0

:Dang、私はインタビューに失敗しました! :-(
「factorize + enumerate divisors + sum them」アプローチを改善するためのトリックやヒューリスティックスを見つけ出す熱心な試みでは、1を法とする9は単にであり、必要なものはであったa 十分な完璧な数字のための条件(6以外)...
Duh ...この条件を満たす平均で1の9の偶数と、私のアルゴリズムは確かに数が多すぎる完全な数を見つけるだろう - )。
自分自身を交換するには、デジタルルートを使用することの提案を維持し、維持しますが、多くの場合、係数のより高価な計算を避けるため、のフィルタとしてのみを使用してください。


[オリジナルの試み:恥のホール]

If the number is even,<br> 
    compute its [digital root][1]. 
     if the digital root is 1, the number is perfect, otherwise it isn't. 

If the number is odd... 
    there are no shortcuts, other than... 
     "Not perfect" if the number is smaller than 10^300 
     For bigger values, one would then need to run the algorithm described in 
     the question, possibly with a few twists typically driven by heuristics 
     that prove that the sum of divisors will be lacking when the number 
     doesn't have some of the low prime factors. 

偶数用のデジタルルートトリックを示唆ための私の理由は、このは、任意の長さの助けを借りずに計算することができるということです算術ライブラリ(GMPなど)また、素因数分解および/または因数分解(2 ^(p-1)*((2^p)-1))よりもはるかに計算量が少なくてであるです。  したがって、インタビュアーが奇数に対して「完璧でない」応答に満足すれば、ソリューションは大部分のコンピューター言語で非常に効率的でコーディング可能になります。


[第2および第3の試み...]この比較的奇妙な面接の質問で

If the number is even,<br> 
    if it is 6 
     The number is PERFECT 
    otherwise compute its [digital root][1]. 
     if the digital root is _not_ 1 
      The number is NOT PERFECT 
     else ..., 
      Compute the prime factors 
      Enumerate the divisors, sum them 
      if the sum of these divisor equals the 2 * the number 
       it is PERFECT 
      else 
       it is NOT PERFECT 

If the number is odd... 
    same as previously 

...
I二andrewdskiの別の応答へのコメントこのポストでは、この特定の質問は、汎用開発者のためのインタビューの文脈ではむしろ奇妙であるということです。
多くのインタビューの質問と同様に、インタビュアーは特定の解決策を模索するのではなく、候補者がさまざまなアプローチの一般的な長所と短所を明確にする能力を発揮する機会を提供することができます。また、候補者がMathWorldやWikipediaなどの一般的なリソースを検索する機会を提供されている場合は、そこに提供されている情報をすばやく理解することができます。

+1

Hmm。 6のデジタルルートは... 6.私は、6が最初の完璧な数字だったと断言できました。はい。デジタルルートトリックは、1桁以上の完全な数字でも機能します。しかし、完璧な数字のために必要な条件です。 10のデジタルルートも1であり、10が完璧ではないと私は誓っていました。 –

+0

@ woodchips:私を現実に戻してくれてありがとう。真実であることがあまりにも素敵に見えているのが普通です。パーフェクトナンバーとメルセンヌナンバーズのすべての接続(デジタルルートテストは本質的にモジュロ9テストです)を除いて、私はそれが簡単ではないと思っていたはずです:-( – mjv

+1

2番目のアルゴリズムが優れていますあなたは完璧ではないと思われる偶数の約90%を除外することができますが、6のデジタルルートが1ではないので、6を完全な数字として識別することができません。 –

0
#include<stdio.h> 
#include<stdlib.h> 
int sumOfFactors(int); 

int main(){ 
int x, start, end; 
    printf("Enter start of the range:\n"); 
    scanf("%d", &start); 
    printf("Enter end of the range:\n"); 
    scanf("%d", &end); 

    for(x = start;x <= end;x++){ 
     if(x == sumOfFactors(x)){ 
      printf("The numbers %d is a perfect number\n", x); 
     } 
    } 
    return 0; 
} 

int sumOfFactors(int x){ 
    int sum = 1, i, j; 
    for(j=2;j <= x/2;j++){ 
     if(x % j == 0) 
      sum += j; 
    } 
    return sum; 
}