Основной коэффициент 300 000 000 000?

Мне нужно выяснить простые множители более 300 миллиардов. У меня есть функция, которая добавляет их к списку ... очень медленно! Он работает уже около часа, и я думаю, что ему достаточно пройти до сих пор. Я делаю это совершенно неправильно или этого ожидают?

Изменить: я пытаюсь найти самый большой простой фактор числа 600851475143.

Изменить: Результат:

{
    List<Int64> ListOfPrimeFactors = new List<Int64>();
    Int64 Number = 600851475143;
    Int64 DividingNumber = 2;

    while (DividingNumber < Number / DividingNumber)
    {
        if (Number % DividingNumber == 0)
        {
            ListOfPrimeFactors.Add(DividingNumber);
            Number = Number/DividingNumber;
        }
        else
            DividingNumber++;
        }
        ListOfPrimeFactors.Add(Number);
        listBox1.DataSource = ListOfPrimeFactors;
    }
}

person xoxo    schedule 13.01.2009    source источник
comment
Пожалуйста, поясните правильным языком, какую точную проблему вы пытаетесь решить. То, что вы объясняете, может иметь как минимум пять или шесть возможных значений. Кроме того, у вас есть какая-нибудь верхняя граница? 10 ^ 40000000000 - это более 300 миллиардов и действительно может занять несколько часов ... :)   -  person Daniel Daranas    schedule 13.01.2009
comment
Вы действительно имеете в виду, что пытаетесь найти простые числа, превышающие 300 000 000 000? (поскольку основным фактором является что-то совсем другое)   -  person Rowland Shaw    schedule 13.01.2009
comment
Вы пытаетесь решить проблему 3 проекта Эйлера?   -  person Perpetualcoder    schedule 13.01.2009
comment
это домашнее задание?   -  person Anthony Potts    schedule 13.01.2009
comment
PerpetualCoder-ДА! И вопрос в том, чтобы найти наибольший простой делитель числа 600851475143 ...   -  person xoxo    schedule 13.01.2009
comment
вам нужно искать только до квадратного корня.   -  person Nicholas Mancuso    schedule 13.01.2009
comment
(1) Прочтите и полностью поймите en.wikipedia.org/wiki/Prime_number (2) Прочтите и полностью понять en.wikipedia.org/wiki/Prime_factor (3) Прочитать и полностью понять en.wikipedia.org/wiki/Integer_factorization (4) Начните думать об алгоритмах (5) Выберите один и закодируй это   -  person Daniel Daranas    schedule 14.01.2009
comment
@Grace: См. Решение XSLT - это всего 2 строчки кода :)   -  person Dimitre Novatchev    schedule 15.01.2009
comment
alpertron.com.ar/ECM.HTM   -  person Ande Turner    schedule 04.07.2009
comment
Простые множители 300000000000 равны [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 , 5];   -  person Larry Battle    schedule 12.05.2012


Ответы (19)


Вы не забываете делить число, которое вы разлагаете на множители, по мере их нахождения?

Скажем, например, вы обнаружите, что 2 - фактор. Вы можете добавить это в свой список факторов, но затем разделите число, которое вы пытаетесь факторизовать, на это значение.

Теперь вы ищете только множители 150 миллиардов. Каждый раз вам следует начинать с того фактора, который вы только что нашли. Итак, если 2 было фактором, проверьте 2 еще раз. Если следующий фактор, который вы найдете, равен 3, снова нет смысла тестировать от 2.

И так далее...

person Alnitak    schedule 13.01.2009
comment
О, хорошо, я понял! Большое спасибо! - person xoxo; 13.01.2009
comment
Изучите исследование рекурсии. - person EBGreen; 13.01.2009
comment
Рекурсия для простого факторинга? - person Eclipse; 13.01.2009
comment
Если BIGNUM = firstFactorFound * (BIGNUM / firstFactorFound), вы можете вычесть BIGNUM / firstFactorFound, чтобы получить остальные факторы. Кроме того, множителями этого нового числа являются ›= firstFactorFound. Вы можете применить это рекурсивно. - person Brian; 13.01.2009
comment
Не забывайте, что вам нужно всего лишь подняться до квадратного корня (нового числа) при факторизации вновь найденного числа. - person Brian; 13.01.2009
comment
Процесс рекурсивный, но я бы не стал реализовывать его как рекурсивную функцию, иначе вы получите ... stackoverflow;) Используйте итерацию. - person Dave Swersky; 13.01.2009
comment
Честно говоря, я бы не стал беспокоиться о стеке, даже без хвостовой рекурсии, размер стека по умолчанию в .NET составляет 1 МБ, поэтому у вас может быть очень много кадров стека, что означает, что если вы можете иметь (x = awful lot ) кадры стека, вы можете факторизовать любое число до x! (и, очевидно, даже больше) - person Tamas Czinege; 13.01.2009

Сложно найти простые множители, используя грубую силу, что похоже на метод, который вы используете.

Вот несколько советов, как это немного ускорить:

  • Начни с малого, а не с высокого
  • Не утруждайтесь проверкой каждого потенциального фактора, чтобы узнать, является ли он простым - просто проверьте ВЕРОЯТНО простые числа (нечетные числа, оканчивающиеся на 1,3,7 или 9).
  • Не беспокойтесь о проверке четных чисел (все делятся на 2) или шансов, которые заканчиваются на 5 (все делятся на 5). Конечно, не пропускайте 2 и 5 !!
  • Когда вы найдете простой множитель, обязательно разделите его - не продолжайте использовать свое массивное исходное число. См. Мой пример ниже.
  • Если вы обнаружите фактор, обязательно проверьте его СНОВА, чтобы увидеть, присутствует ли он там несколько раз. Ваш номер может быть 2x2x3x7x7x7x31 или что-то в этом роде.
  • Остановитесь, когда вы достигнете> = sqrt (оставшееся большое число)

Изменить: простой пример: вы находите коэффициенты 275.

  1. Проверьте 275 на делимость на 2. Неужели 275/2 = int (275/2)? Нет. Не удалось.
  2. Тест 275 на делимость на 3. Неудачный.
  3. Пропустить 4!
  4. Тест 275 на делимость на 5. ДА! 275/5 = 55. Итак, ваш НОВЫЙ номер теста теперь 55.
  5. Проверьте 55 на делимость на 5. ДА! 55/5 = 11. Итак, ваш НОВЫЙ номер теста теперь 11.
  6. НО 5> sqrt (11), поэтому 11 простое, и можно остановиться!

So 275 = 5 * 5 * 11

Больше смысла?

person BradC    schedule 13.01.2009
comment
Что значит «разделить»? И я не уверен, как на это влияет квадратный корень? - person xoxo; 13.01.2009
comment
Если вы не нашли множитель по sqrt числа, вы не найдете его, как бы далеко вы ни зашли. Это ОГРОМНАЯ разница при проверке больших чисел. - person Eclipse; 13.01.2009
comment
Почему вы произносите хотя бы все нечетные числа, оканчивающиеся на 1,3,7 или 9? - person PEZ; 13.01.2009
comment
PEZ: Потому что все числа, оканчивающиеся на 5, не простые, потому что они делятся на 5 (кроме самой 5). Так что пытаться использовать 15, 35 или 105 в качестве возможного фактора - напрасная трата циклов. - person BradC; 13.01.2009
comment
Вы должны уравновесить эти потери с усилиями, необходимыми для пропуска каждого 5-го числа. Вероятно, вы получите больше преимуществ, пропустив каждое третье нечетное число после 3. Обратите внимание, что с компьютерной точки зрения нет ничего особенного в числах, оканчивающихся на 5 в десятичной системе. - person Eclipse; 13.01.2009
comment
Справа - тест-деление каждый раз на 5 слишком расточительно. Просто держите счетчик, который позволяет вам знать, когда увеличивать на 4, а не на 2. В любом случае, однако, он должен быть в состоянии чертовски быстро находить факторы. - person BradC; 13.01.2009
comment
Спасибо за информацию. Я никогда не задумывался над этим фактом. - person PEZ; 13.01.2009
comment
Ответ был действительно хорош. Мне удалось довольно быстро собрать воедино метод Factors () в Python, который занимает 0,002 секунды, чтобы произвести факторы для 600851475143. (Я не стал пропускать те числа, которые заканчиваются на 5). - person PEZ; 13.01.2009
comment
Спасибо, PEZ. Да, факторинг чисел такой величины не должен занимать много времени на современной машине. Конечно, можно добавить к номеру еще несколько цифр ... - person BradC; 14.01.2009
comment
Дайте мне номер, который я могу проверить. =) (может занять менее 10 минут) - person PEZ; 14.01.2009
comment
Что ж, похоже, моя программа не может обрабатывать действительно большие числа. Например, если я дублирую это число (используя 600851475143600851475143), я получаю дерьмовый результат. - person PEZ; 14.01.2009
comment
Да, я делал это на VBA (я знаю, я знаю ...), и он ограничился 14 цифрами. - person BradC; 14.01.2009
comment
Я могу заставить свою программу работать, если я проверю на x * x ‹num вместо вычисления квадратного корня. Конечно, потребуется время, чтобы по-настоящему проверить это огромное количество, поэтому я не уверен, что он работает, но он выполняет некоторую работу, которой не делал раньше. знак равно - person PEZ; 14.01.2009
comment
вы добавляете много циклов, выполняя x * x ‹num каждый цикл. Просто выполните sqrt (num) один раз в начале и сохраните его, затем просто сверяйте с ним каждый цикл (и пересчитывайте, когда найдете коэффициент) - person BradC; 14.01.2009
comment
ну, я не делал x x каждый цикл! =) Мне нравится, что вы предлагаете с sqrt (). но с x x это занимает немного больше времени. для числа, указанного в вопросе, требуется на 20% больше времени. тогда эта разница становится действительно огромной с 13 цифрами. - person PEZ; 14.01.2009
comment
однако сейчас у меня в программе есть еще одна ошибка. занимает 8,5 секунды с номером 60085147514311, правильный результат. затем это занимает 4,5 секунды с 60085147514313, но тогда это не дает мне правильного результата. Я получаю [3], когда должен получать [3, 20028382504771]. - person PEZ; 14.01.2009
comment
Кстати, я вернулся к использованию sqrt () (просто не тупо усекая его до int, как сначала). - person PEZ; 14.01.2009
comment
Что ж, убедитесь, что если ваш цикл заканчивается (когда p ›sqt (n)), то вы предполагаете, что ваше последнее число N является простым и указывается как другой множитель. - person BradC; 14.01.2009
comment
как насчет того, когда начальное число - простое число? это особый случай или о нем следует сообщать как о факторе? - person PEZ; 14.01.2009
comment
Я решил, что имеет смысл не указывать множители для простых чисел. - person PEZ; 14.01.2009
comment
Теперь моя программа работает, я бы сказал, без ошибок. Ему требуется 25 секунд (на моем MacBook), чтобы выяснить, что нет факторов для 600851475143131, и 19 секунд, чтобы сообщить [17, 353442044201843L] для 6008514751431331. Ура! И еще раз спасибо. Это было весело и очень хороший урок для меня. - person PEZ; 14.01.2009
comment
Извините, я не могу перестать играть с этим. =) Для этого числа совсем не требуется время жизни, 600851475143600851475143 (24 цифры). Отчет занимает менее 0,01 секунды [71, 73, 137, 839, 1471, 6857, 99990001]. - person PEZ; 14.01.2009
comment
но я не думал, что 11 - простое число? Разве не делятся на простые множители все простые числа, которые делятся на это число? Или мне вернуться в школу ?! - person xoxo; 14.01.2009
comment
простое число делится только на себя и 1. - person atsjoo; 14.01.2009
comment
@Grace, на твой последний вопрос, да, я так думаю. Здесь есть две проблемы: программирование и решение реальной проблемы. В вашем случае проблема реального мира - это простые числа, и первое, что вам нужно сделать, это изучить теорию о них. Тогда подумайте об алгоритмах. - person Daniel Daranas; 14.01.2009
comment
На самом деле это не для какого-то конкретного проекта, над которым я работаю, просто немного логической практики. И из всего обучения в компании, в которой я работаю, (как ни странно) простые числа никогда не возникали ... Вы не можете сомневаться в моих способностях в программировании, поскольку вы понятия не имеете, за что мне платят! - person xoxo; 14.01.2009
comment
Я не сомневался в твоих способностях к программированию. Я просто сказал, что программирование должно начинаться после того, как вы узнаете, как решить реальную проблему - в данном случае разложение на простые множители. И шаг к решению проблемы - понимание задействованных концепций. - person Daniel Daranas; 14.01.2009

Факторинг больших чисел - сложная проблема. На самом деле настолько сложно, что мы полагаемся на него для обеспечения безопасности RSA. Но взгляните на страницу wikipedia, чтобы найти некоторые указатели на алгоритмы, которые могут помочь. Но для такого небольшого числа это действительно не должно занимать так много времени, если только вы не делаете работу снова и снова, что вам не нужно куда-то.

Что касается решения методом перебора, помните, что вы можете выполнить несколько мини-оптимизаций:

  • Отметьте 2 специально, затем проверьте только нечетные числа.
  • Вам нужно только проверить квадратный корень из числа (если к тому времени вы не найдете множителей, то число будет простым).
  • Найдя множитель, не используйте исходное число для поиска следующего множителя, делите его на найденный множитель и ищите новое меньшее число.
  • Когда вы найдете фактор, разделите его на столько раз, сколько сможете. После этого вам больше не нужно проверять это число или любые меньшие числа.
  • Если вы сделаете все вышеперечисленное, каждый новый фактор, который вы найдете, будет простым, поскольку все меньшие факторы уже удалены.
person Eclipse    schedule 13.01.2009
comment
Число в вопросе несложно и несложно. - person Sam Meldrum; 13.01.2009
comment
Когда мы говорим, что разложить большие числа на множители сложно, мы имеем в виду числа, превышающие примерно 2 ^ 512. RSA и аналогичные, вероятно, используют простые числа около 2 ^ 2048. Число в OP всего около 2 ^ 39 ... намного, намного меньше - person abelenky; 14.01.2009

Вот решение XSLT!

Это преобразование XSLT занимает 0,109 секунды.

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema"
 xmlns:saxon="http://saxon.sf.net/"
 xmlns:f="http://fxsl.sf.net/"
 exclude-result-prefixes="xs saxon f"
 >
 <xsl:import href="../f/func-Primes.xsl"/>

 <xsl:output method="text"/>


 <xsl:template name="initial" match="/*">
   <xsl:sequence select="f:maxPrimeFactor(600851475143)"/>
 </xsl:template>

 <xsl:function name="f:maxPrimeFactor" as="xs:integer">
   <xsl:param name="pNum" as="xs:integer"/>

   <xsl:sequence select=
    "if(f:isPrime($pNum))
       then $pNum
       else
         for $vEnd in xs:integer(floor(f:sqrt($pNum, 0.1E0))),
             $vDiv1 in (2 to $vEnd)[$pNum mod . = 0][1],
             $vDiv2 in $pNum idiv $vDiv1
           return 
             max((f:maxPrimeFactor($vDiv1),f:maxPrimeFactor($vDiv2)))
    "/>
 </xsl:function>
</xsl:stylesheet>

Это преобразование дает правильный результат (максимальный простой фактор 600851475143) всего за 0,109 секунды.:

6857

Преобразование использует f:sqrt() и f:isPrime(), определенная в _5 _ - библиотека для функционального программирования на XSLT . FXSL сам полностью написан на XSLT.

f:isPrime() использует маленькую теорему Ферма. так что определение простоты является эффективным.

person Dimitre Novatchev    schedule 15.01.2009
comment
Как здорово! Жаль, что форум по проблеме 3 закрыт, поэтому вы не можете публиковать это там. Не думаю, что видел там XSLT-решение. - person PEZ; 15.01.2009
comment
Хотя проблема была представлена ​​давно, поэтому форум переполнен, и они закрыли его для новых записей. - person PEZ; 15.01.2009
comment
@PEZ: Спасибо, что упомянули ProjectEuler. Я уже решил 28 задач, и единственным языком программирования, который я использовал, был XSLT. - person Dimitre Novatchev; 23.01.2009
comment
проблемные форумы в проекте Euler снова открыты. Тем не менее, новые сообщения не являются постоянными - они поддерживают не более 100 последних сообщений. Что касается проблемы №3, это было так давно ... 3 недели, прямо сейчас. :) - person Will Ness; 16.10.2012

И последнее, о чем никто не упомянул, возможно, потому, что это кажется очевидным. Каждый раз, когда вы находите фактор и разделяете его, продолжайте пробовать фактор, пока он не потерпит неудачу.

64 имеет только один простой множитель, 2. Вы обнаружите это довольно тривиально, если будете продолжать делить 2 до тех пор, пока больше не сможете.

person user54650    schedule 13.01.2009

$ time factor 300000000000 > /dev/null

real        0m0.027s
user        0m0.000s
sys         0m0.001s

Вы делаете что-то не так, если на это уходит час. У вас может быть даже где-то бесконечный цикл - убедитесь, что вы не используете 32-битные целые числа.

person Community    schedule 13.01.2009

Ключ к пониманию того, почему квадратный корень важен, заключается в том, что каждый множитель n ниже квадратного корня n имеет соответствующий множитель выше. Чтобы увидеть это, представьте, что если x множитель n, то x / n = m, что означает, что x / m = n, следовательно, m также множитель.

person JesperE    schedule 14.01.2009

Я бы не ожидал, что это займет очень много времени - это не очень много.

Не могли бы вы привести пример номера, который вызывает трудности с кодом?

person Jon Skeet    schedule 13.01.2009
comment
600851475143. Я разрезаю его пополам (это то, что я вспомнил из школы), чтобы получилось 300425737571. Я избавляюсь от чисел, делящихся на 2, 3, 5 и 7. Затем я избавляюсь от любых чисел, которые нельзя разделить на число и найдите оставшиеся простые числа ... - person xoxo; 13.01.2009
comment
600851475143. Я разрезал его пополам (это то, что я вспомнил из школы), чтобы получилось 300425737571. Извините ???? Если вы не знаете основной семантики проблемы, не стоит даже пытаться. - person Daniel Daranas; 13.01.2009
comment
Вы попробуете разрезать его пополам? - person Daniel Daranas; 13.01.2009
comment
Я не говорю, что все решения, которые я попробую, будут правильными! Привет, некоторым из нас нравится ненадолго быть любителями! - person xoxo; 14.01.2009
comment
Некоторым из нас это даже нравится! =) В любом случае, вы можете продолжить только с половины, если 2 действительно фактор. Но я думаю, вы уже это поняли. - person PEZ; 14.01.2009
comment
600851475143 и 300425737571 каждый имеет четыре различных простых фактора. У них нет ничего общего. @ Даниэль Даранас предлагает вам понять, почему разрезание [нечетного числа] пополам не работает. Например, вы можете попробовать то же самое с 27, которое сократится до 13, но не имеет делителей с 13. - person A. Rex; 14.01.2009
comment
@A. Рекс, спасибо за разъяснения. Да, я сказал, что вы можете попробовать любые подходы, но это помогает, если они математически верны. Деление числа на 7,65 и последующий логарифм не поможет. - person Daniel Daranas; 14.01.2009
comment
Вы сказали, что не должны даже пытаться. Возможно, это сработает для вас, но для меня попытки - это один из способов понять. Вы новенький совет, чтобы попытаться разобраться в проблеме побольше, прежде чем ее решение будет гораздо более конструктивным. - person PEZ; 14.01.2009
comment
Ах, спасибо PEZ, я просмотрел множество различных алгоритмов для решения этой проблемы, и я уверен, что близок ... (мы можем только надеяться) - person xoxo; 14.01.2009

Вот один сайт, на котором вы можете получить ответы: Factoris - Онлайн-сервис факторизации. Он может обрабатывать действительно большие числа, но также может факторизовать алгебраические выражения.

person zendar    schedule 13.01.2009

Самые быстрые алгоритмы - это ситовые алгоритмы, основанные на тайных областях дискретной математики (по крайней мере, над моей головой), которые сложно реализовать и протестировать.

Самым простым алгоритмом факторинга, вероятно, является (как говорили другие) Решето Эратосфена. Что нужно помнить об использовании этого для множителя числа N:

  • Общая идея: вы проверяете возрастающую последовательность возможных целочисленных множителей x, чтобы увидеть, равномерно ли они делят ваш номер кандидата N (в C / Java / Javascript проверяйте, N % x == 0), и в этом случае N не является простым.
  • вам просто нужно подняться до sqrt(N), но на самом деле не вычислять sqrt(N): loop, пока ваш тестовый фактор x проходит тест x*x<N
  • если у вас есть память, чтобы сохранить кучу предыдущих простых чисел, используйте только их в качестве тестовых факторов (и не сохраняйте их, если простое P не проходит тест P*P > N_max, так как вы никогда не будете использовать их снова
  • Даже если вы не сохраните предыдущие простые числа, для возможных множителей x просто отметьте 2 и все нечетные числа. Да, это займет больше времени, но не намного дольше для чисел разумного размера. функция подсчета простых чисел и ее приближения могут сказать вам, какая доля чисел является простой; эта доля уменьшается очень медленно. Даже для 2 64 = приблизительно 1,8x10 19 примерно одно из каждых 43 чисел является простым (= одно из каждых 21,5 нечетных чисел является простым). Для множителей чисел меньше 2 64 эти множители x меньше 2 32, где примерно одно из каждых 20 чисел является простым = одно из каждых 10 нечетных чисел равно основной. Таким образом, вам придется протестировать в 10 раз больше чисел, но цикл должен быть немного быстрее, и вам не придется возиться с хранением всех этих простых чисел.

Есть также несколько более старых и простых алгоритмов сита, которые немного сложнее, но все же довольно понятны. См. Диксон, Shanks ' и Ферма алгоритмы факторинга. Я однажды прочитал статью об одном из них, не могу вспомнить, какой из них, но все они довольно просты и используют алгебраические свойства разностей квадратов.

Если вы просто проверяете, является ли число N простым, и на самом деле не заботитесь о самих факторах, используйте вероятностный тест на простоту. Я думаю, что Миллера-Рабина является наиболее стандартным.

person Jason S    schedule 13.01.2009
comment
Когда я делаю x * x ‹N вместо x‹ sqrt (N), для рассматриваемого числа требуется больше времени (в Python). Может быть, sqrt (N) сводит сравнение к целым типам, которые сравниваются быстрее? - person PEZ; 14.01.2009
comment
если N фиксировано, возможно, интерпретатор достаточно умен, чтобы оценить его только один раз ... - person Jason S; 14.01.2009
comment
В другом потоке факторизации я провел тест на Sieve - он абсолютно STUNK, даже когда противостоит грубому алгоритму, который не учел всех перечисленных здесь приемов. (Не то чтобы я уверен, что все уловки хороши - стоимость может быть выше, чем они экономят!) - person Loren Pechtel; 14.01.2009
comment
Джейсон, дело в том, что я не очень часто вычисляю sqrt (N), только когда нахожу множитель. Это сравнение происходит часто. Может быть (мои тесты показывают, что это намного) эффективнее сравнивать p ‹sqrt_N, чем p_times_p‹ N. - person PEZ; 14.01.2009

Я потратил на это некоторое время, так как меня это просто затянуло. Я пока не буду вставлять здесь код. Вместо этого, если вам интересно, просмотрите this factor.py gist.

Имейте в виду, я ничего не знал о факторинге (до сих пор не знаю) до того, как прочитал этот вопрос. Это просто Python-реализация ответа BradC, приведенного выше.

На моем MacBook требуется 0,002 секунды, чтобы разложить на множитель число, указанное в вопросе (600851475143).

Очевидно, должны быть гораздо более быстрые способы сделать это. Моей программе требуется 19 секунд для вычисления множителей 6008514751431331. Но Factoris выдаст ответ в кратчайшие сроки.

person PEZ    schedule 14.01.2009
comment
Это форум на сайте Project Euler (projecteuler.net), к которому вы получаете доступ после отправки правильного ответ на проблему, которую мы здесь обсуждаем. Проверить это. Но предупреждаю; Это очень затягивает! - person PEZ; 15.01.2009
comment
@PEZ: Большое спасибо за упоминание ProjectEuler. Я уже решил 28 задач, и единственным языком программирования, который я использовал, был XSLT. - person Dimitre Novatchev; 23.01.2009
comment
Это восхитительно. Разве вы не можете разместить свои решения на gist.github.com или что-то в этом роде. Я хотел бы увидеть еще несколько XSLT-решений проблем, которые я решил. И последняя проблема была запущена на прошлой неделе, поэтому, если вы решите ее, вы, вероятно, сможете опубликовать сообщение на форуме проекта. Завтра они запускают новую задачу. - person PEZ; 23.01.2009

Конкретный номер 300425737571? Это тривиально превращается в 131 * 151 * 673 * 22567. Я не понимаю, в чем вся суета ...

person Community    schedule 08.07.2009

Вот вам добрые дела от Haskell :)

primeFactors n = factor n primes
  where factor n (p:ps) | p*p > n = [n]
                        | n `mod` p /= 0 = factor n ps
                        | otherwise = p : factor (n `div` p) (p:ps)
        primes = 2 : filter ((==1) . length . primeFactors) [3,5..]

На их поиск потребовалось около 0,5 секунды, так что я бы назвал это успехом.

person Alex Fort    schedule 13.01.2009
comment
Он? Я она! и нет, я не просил код в исходном вопросе, но это не тот язык, который я использую, поэтому его не беспокоит! - person xoxo; 14.01.2009
comment
Если вы не просеиваете, это меньше кода и быстрее: primeFactors n = factor n (2: [3,5 ..]) - person A. Rex; 14.01.2009
comment
обратные кавычки вокруг мода и div не отображались. Любой, кто пытается использовать этот код, ставит `обратные кавычки` вокруг mod и div. @A. Рекс: всегда быстрее? или как раз в данном случае? Помогло бы сито больше при увеличении входного числа? - person LarsH; 18.08.2010

Вы можете использовать сито Эратосфена, чтобы найти простые числа и посмотреть, делится ли ваше число на эти ты ищешь.

person Sam Meldrum    schedule 13.01.2009
comment
сито работает очень медленно по сравнению с простой проверкой каждого нечетного числа. - person zaratustra; 13.01.2009

Вам нужно только проверить его остаток по модулю (n), где n - простое число ‹= sqrt (N), где N - число, которое вы пытаетесь разложить на множители. Это действительно не должно занять больше часа, даже на очень медленном компьютере или TI-85.

person Anthony Potts    schedule 13.01.2009
comment
Вздыхает нет, я думаю, это просто мое незнание простых чисел! - person xoxo; 13.01.2009
comment
До того, как я стал программистом, я был аспирантом по теории чисел, и, похоже, есть ряд других людей, которые тоже этим занимаются. Как упоминалось в других сообщениях, простые числа - это то, что обеспечивает безопасность всего. Если у вас есть время и оно вас интересует, проверьте его. - person Anthony Potts; 14.01.2009

Ваш алгоритм должен быть FUBAR. На моем нетбуке с тактовой частотой 1,6 ГГц на Python это занимает всего 0,1 с. Python не известен своей молниеносной скоростью. Однако он имеет целые числа произвольной точности ...

import math
import operator

def factor(n):
    """Given the number n, to factor yield a it's prime factors.
    factor(1) yields one result: 1. Negative n is not supported."""
    M = math.sqrt(n)  # no factors larger than M
    p = 2             # candidate factor to test
    while p <= M:     # keep looking until pointless
        d, m = divmod(n, p)
        if m == 0:
            yield p   # p is a prime factor
            n = d     # divide n accordingly
            M = math.sqrt(n)  # and adjust M
        else:
            p += 1    # p didn't pan out, try the next candidate
    yield n  # whatever's left in n is a prime factor

def test_factor(n):
    f = factor(n)
    n2 = reduce(operator.mul, f)
    assert n2 == n

def example():
    n = 600851475143
    f = list(factor(n))
    assert reduce(operator.mul, f) == n
    print n, "=", "*".join(str(p) for p in f)

example()

# output:
# 600851475143 = 71*839*1471*6857

(Этот код, кажется, работает вопреки тому факту, что я недостаточно разбираюсь в теории чисел, чтобы заполнить наперсток.)

person bendin    schedule 13.01.2009
comment
Вам повезло с выбором: 71 появляется довольно быстро, что значительно сокращает затраченное время. Попробуйте разложить на множители это: 12073531234081300153 - person Jason S; 13.01.2009
comment
Да, естественно, даже этот довольно глупый алгоритм был бы лучше, если бы он не тратил время на попытки значений p, которые не являются простыми. Однако я должен отметить, что в вопросе конкретно упоминается 600851475143, так что это не было удачей как таковой. ;-) - person bendin; 13.01.2009

Просто чтобы немного расширить / улучшить предложения "только проверять нечетные числа, не заканчивающиеся на 5" ...

Все простые числа больше 3 либо на единицу больше, либо на единицу меньше кратного 6 (6x + 1 или 6x - 1 для целых значений x).

person Dave Sherohman    schedule 14.01.2009

Это не займет так много времени, даже с относительно наивной грубой силой. Для этого конкретного числа я могу мысленно разложить его примерно за одну секунду.

Вы говорите, что не хотите решений (?), Но вот ваш "тонкий" намек. Единственные простые множители числа - это три младших простых числа.

person recursive    schedule 13.01.2009
comment
Я почти не хочу знать ответ на этот вопрос ... но зачем вам фактор ТОЛЬКО этого конкретного числа? - person EdgarVerona; 13.01.2009

Полупростые числа такого размера используются для шифрования, поэтому мне любопытно, для чего именно вы хотите их использовать.

Помимо этого, в настоящее время нет хороших способов найти разложение больших чисел на простые множители за относительно небольшой промежуток времени.

person Matthew Brubaker    schedule 13.01.2009
comment
Правда в части менее 40 бит, моя ошибка. Однако каждое простое число шифрования iirc обычно составляет 512 бит (всего 1024 бита для результирующего ключа). Вы используете два, умножаете их и получаете полупростое число (число только с двумя простыми множителями). - person Matthew Brubaker; 13.01.2009