Алгоритм для проверки, если число, если идеальное число
Я ищу алгоритм, чтобы найти, является ли данное число идеальным числом.
самое простое, что приходит мне на ум:
- найти все делители числа
- получить простые множители [кроме самого числа, если оно простое] и сложить их, чтобы проверить, если это идеальное число.
есть ли лучший способ сделать это ?. При поиске некоторые евклиды работали, но не нашли хорошего алгоритма. Также это golfscript не был полезен: https://stackoverflow.com/questions/3472534/checking-whether-a-number-is-mathematically-a-perfect-number .
числа и т. д. могут быть кэшированы и т. д. В реальном мире [который я не знаю, где используются идеальные nos:)]
Однако, поскольку это задается в интервью, я предполагаю, что должен быть "производный" способ его оптимизации.
спасибо !
4 ответов
Если вход четный, посмотрите, имеет ли он форму 2^(p-1)*(2^p-1)
с p
и 2^p-1
премьер.
Если вход нечетный, верните "false". :-)
посмотреть Википедия страницы для сведения.
(на самом деле, так как есть только 47 идеальных чисел с менее чем 25 миллионов цифр, вы можете начать с простой таблицы из них. Спросите интервьюера, можно ли предположить, что вы используете 64-разрядные номера, например...)
редактировать: Данг, я провалил собеседование! :-(
В моей чрезмерно рьяной попытке найти трюки или эвристику, чтобы улучшить подход "факторизировать + перечислять делители + суммировать их", я не заметил, что быть 1 по модулю 9 было просто необходимые и, конечно, не достаточное условие для номера at (кроме 6), чтобы быть идеальным...
Да... в среднем 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)). Поэтому, если интервьюер удовлетворится ответом" нет идеального " для нечетных чисел, решение будет очень эффективным и кодируемым на большинстве компьютерных языков.
[вторая и третья попытка...]
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
на этом относительно странный вопрос интервью...
Я второй andrewdskiкомментарий к другому ответу в этом посте, что этот конкретный вопрос довольно странный в контексте интервью для разработчика общего назначения.
как и во многих вопросах интервью, может быть, что интервьюер не ищет конкретного решения, а скорее предоставляет возможность кандидату продемонстрировать свою способность сформулировать общие плюсы и минусы различных подходы. Кроме того, если кандидату предлагается возможность поиска общих ресурсов, таких как MathWorld или Wikipedia, до ответа, это также может быть хорошей проверкой его/ее способности быстро понять информацию, предлагаемую там.
вот быстрый алгоритм просто для удовольствия, в PHP-используя только простой for
петли. Вы можете easliy порт, что на другие языки:
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.';
}
надеюсь, это поможет, не уверен, что это то, что вы ищете.
#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;
}