Я не буду решать, что лучший алгоритм, чтобы найти все факторы целое есть. Вместо этого я хотел бы прокомментировать ваш текущий метод.
Есть ты условными тесты дел рассмотреть
(divider * divider) <= number
divider <= number/divider
divider <= sqrt(number)
См Conditional tests in primality by trial division для более detials.
Корпус для использования зависит от ваших целей и оборудования.
Преимущество случая 1 состоит в том, что он не требует разделения. Однако он может переполняться, когда divider*divider
больше, чем наибольшее целое число. Второй случай не имеет проблемы с переполнением, но требует разделения. Для case3 sqrt
нужно рассчитать только один раз, но для этого требуется, чтобы функция sqrt
вернулась к идеальным квадратам.
Но есть что-то еще, чтобы рассмотреть множество наборов инструкций, включая набор команд x86, и вернуть остальную часть при выполнении деления. Поскольку вы уже делаете number % divider
, это означает, что вы получаете его бесплатно при выполнении number/divider
.
Следовательно, случай 1 полезен только в системе, где деление и остаток не вычисляются в одной инструкции, и вы не беспокоитесь о переполнении.
Между корпусом 2 и корпусом 3 Я думаю, что основной проблемой является снова набор инструкций. Выберите случай 2, если sqrt
слишком медленный по сравнению с case2 или если ваша функция sqrt
не вычисляет идеальные квадраты правильно. Выберите случай 3, если набор команд не вычисляет делитель и остаток в одной инструкции.
Для случая набора команд x86 1, случай 2 и случай 3 должны обеспечивать по существу равную производительность. Так что должен не иметь причины использовать случай 1 (однако см. Тонкий пункт ниже). Стандартная библиотека C гарантирует, что совершенные квадраты sqrt
выполнены правильно. Таким образом, нет недостатка в случае 3.
Но есть один тонкий момент о случае 2. Я обнаружил, что некоторые компиляторы не признают, что деление и остаток вычисляются вместе. Например, в следующем коде
for(divider = 2; divider <= number/divider; divider++)
if(number % divider == 0)
GCC генерирует две инструкции разделения, хотя требуется только одна. Один из способов исправить это, чтобы сохранить разделение и напоминание близко, как этот
divider = 2, q = number/divider, r = number%divider
for(; divider <= q; divider++, q = number/divider, r = number%divider)
if(r == 0)
В этом случае GCC производит только одну инструкцию деления и case1, корпус 2 и корпус 3 имеют одинаковую производительность. Но этот код немного менее читабельный, чем
int cut = sqrt(number);
for(divider = 2; divider <= cut; divider++)
if(number % divider == 0)
, так что я думаю, в целом случай 3 является лучшим выбором, по крайней мере с набором команд x86.
@RSahu Я не верю, что это правильный дубликат. Пожалуйста, откройте снова. – fuz
@FUZxxl, я был предвзятым по названию. –
С небольшим количеством исследований вы можете перефразировать свой вопрос так: «Что такое эффективный алгоритм для нахождения всех факторов целого числа?» Я думаю, вы обнаружите, что это довольно глубокий вопрос, который много раз обсуждался на этом форуме ... – Steger