2011-07-04 60 views
6

Tôi đang tìm một thuật toán để tìm số liệu đã cho có phải là số hoàn hảo hay không.Thuật toán để kiểm tra xem một số có phải là số hoàn hảo

Các đơn giản nhất mà nói đến cái tâm của tôi là:

  1. Tìm tất cả các yếu tố của số
  2. Lấy thừa số nguyên tố [ngoại trừ số chính nó, nếu nó là số nguyên tố] và thêm họ lên kiểm tra nếu nó là một số hoàn hảo.

Có cách nào tốt hơn để thực hiện việc này không? Khi tìm kiếm, một số công trình Euclids đã xuất hiện, nhưng không tìm thấy bất kỳ thuật toán tốt nào. Ngoài ra golfscript này không hữu ích: https://stackoverflow.com/questions/3472534/checking-whether-a-number-is-mathematically-a-perfect-number.

Các số vv có thể được lưu trong bộ nhớ cache, vv ..
Tuy nhiên, vì điều này đang được hỏi trong các cuộc phỏng vấn, tôi giả định rằng nên có một "có thể phát sinh" cách tối ưu hóa nó.

Cảm ơn!

+1

Hãy coi chừng, đối với bướC# 2 của bạn, nó không phải là tổng của các yếu tố _prime_ của nó, mà là _all_ các yếu tố của nó. ví dụ. 28 là hoàn hảo bởi vì 1 + 2 + 4 + 7 + 14 = 28 (lưu ý các yếu tố 4 và 14). – mjv

+0

thnx, tôi đã sửa chữa điều đó. – codeObserver

Trả lời

9

Nếu đầu vào là số chẵn, hãy xem nó có ở dạng 2^(p-1)*(2^p-1), với p2^p-1 chính.

Nếu đầu vào là số lẻ, trả về "false". :-)

Xem chi tiết Wikipedia page.

(Thực tế, vì chỉ có 47 số hoàn hảo với ít hơn 25 triệu chữ số, bạn có thể bắt đầu bằng một bảng đơn giản. Hãy hỏi người phỏng vấn nếu bạn có thể giả sử bạn đang sử dụng số 64 bit, ví dụ .. .)

+5

Có được cả hai đầu của câu hỏi phỏng vấn như thế này, tôi tự hỏi nếu họ đang mong đợi một cái gì đó giống như bảng câu trả lời. Có vẻ như nó đang hỏi về kiến ​​thức đặc biệt khủng khiếp. Tôi muốn ai đó có thể lập trình, không phải ai đó biết lý thuyết số. – andrewdski

+1

Lưu ý bài kiểm tra chuyên ngành [Lucas-Lehmer] (http://en.wikipedia.org/wiki/Lucas%E2%80%93Lehmer_primality_test) về tính nguyên thủy của số Mersenne (2^p) -1. – hardmath

+0

thnx cho liên kết. Tôi nghĩ rằng không có tối ưu hóa derivable .. vì vậy nếu sử dụng một bảng doesnt làm việc ... thì có lẽ những người phỏng vấn cần một nhà toán học có thể viết mã nhiều hơn một lập trình viên có thể sử dụng toán học! – codeObserver

0

Đây là thuật toán nhanh chỉ để giải trí, bằng PHP - chỉ sử dụng vòng lặp for đơn giản. Bạn có thể easliy cổng đến các ngôn ngữ khác:

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

Hy vọng điều này sẽ giúp, không chắc chắn nếu đây là những gì bạn đang tìm kiếm.

+0

Trong khi chức năng chính xác, việc thực hiện này là tối ưu nhưng nhược điểm chính của nó là phạm vi hoạt động của nó bị ràng buộc với số nguyên PHP trong thế giới số hoàn hảo/mersennes là một số khá nhỏ ;-) Bạn nên sử dụng GMP (số nguyên chiều dài tùy ý) nếu bạn muốn vượt quá giới hạn 2^PHP_INT_SIZE. – mjv

+0

thnx, tôi đang tìm cách thực hiện điều này nhanh hơn. Bắt nó với số lượng lớn hơn sẽ chậm? – codeObserver

+0

Sẽ không có ý nghĩa gì khi thêm số chia ngay sau khi bạn tìm thấy chúng hơn là lưu chúng và thêm sau? Ngoài ra, nhìn thấy khi tôi bắt đầu từ 2, không nên nếu điều kiện là '$ sum + 1 == $ num' – rath

0

Chỉnh sửa: Dang, Tôi đã thất bại trong cuộc phỏng vấn! :-(
Trong nỗ lực hết sức sốt sắng của tôi khi tìm kiếm thủ thuật hoặc chẩn đoán để cải thiện phương pháp "factorize + enumerate divisors + sum them", tôi không lưu ý rằng 1 modulo 9 chỉ là cần thiết và chắc chắn không a đủ điều kiện cho số (không phải 6) là hoàn hảo ...
Duh ... với số trung bình 1 trong 9 thậm chí số thỏa mãn điều kiện này, thuật toán của tôi chắc chắn sẽ tìm thấy một số quá hoàn hảo;).
Để tự đổi, duy trì và duy trì đề xuất sử dụng gốc kỹ thuật số, nhưng chỉ làm bộ lọc, để tránh tính toán yếu tố đắt tiền hơn, trong hầu hết các trường hợp.


[Original nỗ lực: hội trường của sự xấu hổ]

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. 

lý do của tôi cho thấy các trick gốc kỹ thuật số cho các số chẵn là này có thể được tính mà không cần sự giúp đỡ của một chiều dài tùy ý thư viện số học (như GMP). Nó cũng là ít tốn kém hơn nhiều tính toán so với sự phân hủy trong các hệ số nguyên tố và/hoặc hệ số hóa (2^(p-1) * ((2^p) -1)).   Do đó, nếu người phỏng vấn hài lòng với câu trả lời "Không hoàn hảo" cho số lẻ, giải pháp sẽ rất hiệu quả và có thể mã hóa được bằng hầu hết các ngôn ngữ máy tính.


[Thứ hai và thứ ba nỗ lực ...]

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 

Về câu hỏi phỏng vấn tương đối kỳ lạ này ...
Tôi thứ hai andrewdski 's bình luận cho câu trả lời khác trong bài đăng này, câu hỏi cụ thể này khá kỳ quặc trong bối cảnh cuộc phỏng vấn cho một nhà phát triển có mục đích chung.
Như với nhiều câu hỏi phỏng vấn, có thể người phỏng vấn không tìm kiếm một giải pháp cụ thể, mà là cung cấp cơ hội cho ứng cử viên thể hiện khả năng của mình để nói lên những ưu và khuyết điểm chung của các cách tiếp cận khác nhau. Ngoài ra, nếu ứng cử viên được cung cấp một cơ hội để tìm kiếm các tài nguyên chung như MathWorld hoặc Wikipedia trước khi trả lời, đây cũng có thể là một thử nghiệm tốt về khả năng của mình để nhanh chóng hiểu được thông tin được cung cấp ở đó.

+1

Hmm. Các gốc kỹ thuật số của 6 là ... 6. Tôi có thể đã tuyên thệ 6 là số hoàn hảo đầu tiên. Vâng, mẹo gốc kỹ thuật số hoạt động cho các số chẵn hoàn hảo với hơn 1 chữ số. Nhưng nó chỉ là một điều kiện cần thiết cho một số hoàn hảo. Gốc kỹ thuật số của 10 cũng là 1, và tôi có thể thề rằng 10 không hoàn hảo. –

+0

@woodchips: Cảm ơn bạn đã đưa tôi trở lại thực tế. Khi một cái gì đó trông quá đẹp để trở thành sự thật thường là trường hợp. Với tất cả các kết nối của số hoàn hảo để số Mersenne (và ngoài thực tế là các bài kiểm tra gốc kỹ thuật số về cơ bản là một bài kiểm tra modulo 9), tôi nên đã nghĩ rằng nó sẽ không được dễ dàng :-( – mjv

+1

Thuật toán thứ hai của bạn là tốt hơn , cho phép bạn loại trừ khoảng 90% số chẵn là không hoàn hảo. Tuy nhiên, nó vẫn sẽ bỏ lỡ việc xác định 6 là một số hoàn hảo vì gốc kỹ thuật số của 6 là 6, chứ không phải 1. –

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; 
} 
Các vấn đề liên quan