Исключение нулевого указателя генерируется, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:
null
. null
. null
, как если бы это был массив. null
, как если бы это был массив. null
как будто это было значение Throwable. Приложения должны бросать экземпляры этого класса, чтобы указать на другие незаконные использования объекта null
.
Ссылка: http://docs.oracle.com/javase/8/docs/api/java/lang/NullPointerException.html
Для начала, вместо того, чтобы начать Ваш поиск в n / 2, запустите его в квадратном корне n. Вы получите половину факторов, другое наполовину быть их дополнением.
, например:
n = 27
start at floor(sqrt(27)) = 5
is 5 a factor? no
is 4 a factor? no
is 3 a factor? yes. 27 / 3 = 9. 9 is also a factor.
is 2 a factor? no.
factors are 3 and 9.
Необходимо уменьшить объем проверки, что Вы делаете... думают, о каких числах необходимо протестировать.
Для лучшего чтения подхода на Решето Erathosthenes... это должно получить Вас, указал в правильном направлении.
Попытайтесь использовать Тест Простоты чисел Miller-Rabin для тестирования на число, являющееся главным. Это должно значительно ускорить вещи.
Другой подход должен получить все начала до n/2 сначала и затем проверять, ли модуль 0. Алгоритм, который я использую для получения всех начал [до 112] n, может быть найден здесь .
Хотя вопрос просит самый большой простой множитель, это не обязательно означает, что необходимо найти что одно первое...
Все проблемы Euler's Проекта должны занять меньше затем минуту; даже неоптимизированная рекурсивная реализация в Python занимает меньше затем секунду [0.09 secs (CPU 4.3 ГГц)].
from math import sqrt
def largest_primefactor(number):
for divisor in range(2, int(sqrt(number) + 1.5)): # divisor <= sqrt(n)
q, r = divmod(number, divisor)
if r == 0:
#assert(isprime(divisor))
# recursion depth == number of prime factors,
# e.g. 4 has two prime factors: {2,2}
return largest_primefactor(q)
return number # number is a prime itself
Путем я сделал это должно было искать начала (p
), запускающийся при 2 использованиях Решета Эратосфена. Этот алгоритм может найти все начала менее чем 10 миллионами в < 2 с на прилично быстрой машине.
Для каждого начала Вы находите, тест делят его на число, которое Вы тестируете против того, непока Вы не можете больше делать целочисленного деления. (т.е. проверьте n % p == 0
и если это правда, затем разделитесь.)
Однажды n = 1
, Вы сделаны. Последнее значение n
, который успешно разделился, является Вашим ответом. На заметке на полях Вы также нашли все простые множители n
на пути.
пз: Как отмечено прежде, только необходимо искать начала между 2 <= n <= sqrt(p)
. Это делает Решето Эратосфена очень быстрым и легким для реализации алгоритма в наших целях.
Что касается причины для ответа принятого nicf:
Это хорошо для проблемы в Euler, но не делает это эффективным решением в общем случае. Почему Вы попробовали бы четные числа за факторы?
Это привело бы к некоторому коду как это:
n = abs(number);
result = 1;
if (n mod 2 = 0) {
result = 2;
while (n mod 2 = 0) n /= 2;
}
for(i=3; i<sqrt(n); i+=2) {
if (n mod i = 0) {
result = i;
while (n mod i = 0) n /= i;
}
}
return max(n,result)
существуют некоторые тесты по модулю, которые являются лишними, поскольку n никогда не может делиться на 6, если все факторы 2 и 3 были удалены. Вы могли только позволить начала поскольку я.
Так же, как пример позволяет взгляду на результат для 21:
21 даже не, таким образом, мы входим для цикла с верхним пределом sqrt (21) (~4.6). Мы можем затем разделить 21 на 3, поэтому закончиться = 3 и n = 21/3 = 7. Мы теперь только должны протестировать до sqrt (7). который меньше затем 3, таким образом, мы, покончили для цикла. Мы возвращаем макс. из n и результата, который является n = 7.
Используя рекурсивный алгоритм в меньше выполнений Java, чем секунда... продумывает Ваш алгоритм немного, поскольку он включает некоторое "принуждение скота", которое может быть устранено. Также посмотрите на то, как Ваше пространство решения может быть уменьшено промежуточными вычислениями.
На самом деле для этого случая Вы не должны проверить на простоту чисел, просто удалить факторы, которые Вы находите. Запустите с n == 2 и просканируйте вверх. Когда % злого большого числа n == 0, разделите злое большое число на n и продолжите меньшее злое число. Остановитесь когда n> = sqrt (большое злое число).
не Должен брать больше, чем несколько секунд ни на какой современной машине.
вы можете увидеть это: Есть ли простой алгоритм, который может определить, является ли X простым, и не запутать простого смертного программиста?
и мне нравится решение Лилла грязи:
require "mathn.rb"
помещает 600851475143.prime_division.last.first
Я проверил это здесь
long n = 600851475143L; //not even, so 2 wont be a factor
int factor = 3;
while( n > 1)
{
if(n % factor == 0)
{
n/=factor;
}else
factor += 2; //skip even numbrs
}
print factor;
Это должно быть достаточно быстро... Заметьте, нет необходимости проверять наличие прайма...
Как только найдете ответ, введите в браузере следующее ;)
http://www.wolframalpha.com/input/?i=FactorInteger(600851475143)
Wofram Alpha - ваш друг
Easy peasy в C ++:
#include <iostream>
using namespace std;
int main()
{
unsigned long long int largefactor = 600851475143;
for(int i = 2;;)
{
if (largefactor <= i)
break;
if (largefactor % i == 0)
{
largefactor = largefactor / i;
}
else
i++;
}
cout << largefactor << endl;
cin.get();
return 0;
}