Project Euler # 3 Проблема решения Java - PullRequest
1 голос
/ 01 ноября 2009
class eulerThree {

    public static void main(String[] args) {

        double x = 600851475143d; 

        for (double z = 2; z*z <= x; z++) {

            if (x%z == 0) {

                System.out.println(z + "PRIME FACTOR");

            }

        }

    }

}

и вывод:

71.0
839.0
1471.0
6857.0
59569.0
104441.0
486847.0

Итак, я предполагаю, что 486847 - это наибольший простой множитель x, но проект Эйлер говорит иначе. Я не вижу проблемы в своем коде или моей математике, поэтому я в замешательстве. Ты видишь что-нибудь, что я не могу?

Ответы [ 8 ]

4 голосов
/ 01 ноября 2009

Во-первых, вы должны использовать точные арифметические средства. Другие предложили использовать BigInteger. Вы можете сделать это. Для меня это немного похоже на читерство (это будет более важно для последующих задач, связанных с гораздо большими целыми числами), поэтому более забавный способ (imho) - написать необходимые операции произвольной точности самостоятельно.

Во-вторых, 600851475143 достаточно мал, чтобы быть точным с long, что будет намного быстрее.

В-третьих, ваш цикл неправильно проверяет основные факторы. Вы просто проверяете нечетные числа. Это базовое (неполное) решение:

long num = 600851475143L;
List<Long> factors = new ArrayList<Long>(); // or use a Set
if (num & 1 == 0) {
  factors.add(2L);
}
for (long i=3; i*i<=num; i+=2) {
  // first check i is prime
  // if i is prime check if it is a factor of num
}

Проверка, является ли что-то простое, имеет разные уровни реализации. Самые наивные:

public boolean isPrime(long num) {
  for (long i=2; i<=num; i++) {
    if (num % i == 0) {
      return false;
    }
  }
  return true;
}

Конечно, это делает все виды ненужной проверки. Как вы уже определили, вам нужно только проверить числа до sqrt(n), и вы можете удалить четные числа (кроме 2):

public boolean isPrime(long num) {
  if (num & 1 == 0) {
    return false; // checks divisibility by 2
  }
  for (long i=3; i*i<=num; i+=2) {
    if (num % i == 0) {
      return false;
    }
  }
  return true;
}

Но вы тоже можете добиться большего. Другая оптимизация заключается в том, что вам нужно проверять число только по простым числам в этом диапазоне. Основными множителями 63 являются 3 и 7. Если число не делится на 3 или 7, то оно по определению не делится на 63.

Итак, вы хотите построить, вероятно, Set<Long> или простые числа, пока квадрат не станет равным или больше, чем ваше целевое число. Затем просто проверьте эту серию чисел на делимость на цель.

2 голосов
/ 01 ноября 2009

double изначально неточен для больших значений и должен никогда не использоваться для этого типа операций с числами. Правильный класс для использования - BigInteger, что позволяет точно представлять произвольно большие интегральные значения. См. эту статью в Википедии для описания того, что типы данных с плавающей запятой являются и не являются.

1 голос
/ 01 ноября 2009

Две вещи:

  1. Не используйте double, чем больше число, тем меньше точность. Вместо этого вы можете использовать BigInteger для хранения произвольно больших целых чисел, или в этом случае будет достаточно простого long.

  2. Вам нужно разделить на главный фактор после того, как вы его найдете, иначе вы найдете все факторы, а не только простые факторы. Примерно так:

    if (x % z == 0) {
        System.out.println(z + "PRIME FACTOR");
        x /= z;
        z -= 1; // Might be present multiple times, try it again
    }
    
1 голос
/ 01 ноября 2009

Во-первых, используйте BigInteger или long, а не double. Двойное не является точным, и, как вы получите к более поздним проблемам, это не будет правильным вообще.

Во-вторых, то, что вы печатаете, это факторы, а не главные факторы.

Это будет работать в вашем случае:

for (double z = 2; z <= x; z++) {
        if (x%z == 0) {
                    while( x%z == 0)
                        x = x/z
                System.out.println(z + "PRIME FACTOR");
        }
}

Кроме того, Project Euler дает вам пример ввода и вывода. Используйте это, поскольку ваш код не выводит значения, которые соответствуют примеру, который они приводят в задаче.

0 голосов
/ 18 июля 2015
package findlaragestprimefactor;

public class FindLaragestPrimeFactor{

    boolean isPrime(long number) {
        for (long divider = 2; divider <= number / 2; divider++) {
            if (number % divider == 0) {
                return false;
            }

        }
        return true;
    }

    void calculateLargestPrimeFactor() {
        long largestPrimeFactor = 0;
        long x = 600851475143L;
        for(long factor = 3 ; factor <= x/2 ; factor = factor + 2){
            if(x%factor==0 & factor>largestPrimeFactor & isPrime(factor)){
                largestPrimeFactor = factor;
            }
        }
        System.out.println(largestPrimeFactor);
    }







    public static void main(String[] args) {

        MyProject m = new MyProject();
        m.calculateLargestPrimeFactor();
    }
}
0 голосов
/ 11 июля 2015
public static void largestPrimeNo(long lim)
{
long newNum = lim;
long largestFact = 0;

int counter = 2;
while( counter * counter <= newNum )
{
if(newNum % counter == 0)
{
    newNum = newNum / counter;
    largestFact = counter;
}else{
counter++;
}
}
if(newNum > largestFact)
{
largestFact=newNum;
}
System.out.println(largestFact);
}
}

, поскольку Prime no работает по принципу, что Любое целое число больше 1 является либо простым числом, либо может быть записано как уникальный продукт простых чисел . Так что мы можем легко использовать вышеуказанную программу. В этой программе мы делим длинное нет и находим ее главный множитель

0 голосов
/ 14 февраля 2013
          import java.util.Scanner;

          class Primefactor
                   {
                          public static void main(String args[])
                              {
                       Scanner get=new Scanner(System.in);
                       System.out.println("Enter a number");
                       long number=get.nextLong();
                       int count=0;
                       long input=number;
                             for(long i=number;i>=1;number--)
                                 {
                    for(long j=number;j>=1;j--)
                     {
                       if(i%j==0)
                         {
                            count++;
                         }
                      if(count==2)
                        {
                           if(input%j==0)
                              {
                                 System.out.println(j);
                               }
                           }
                     }
                  }
            }
          }

Это чтобы увидеть наибольший главный фактор любого числа в пределах предела типа данных.

0 голосов
/ 21 августа 2012
public class Prime {
    public static void main(String[] args) {
        double out = 0;
        double m = 600851475143d;
        for (double n = 3; n < m; n += 2) {
            while (m % n == 0) {
                out = n;
                m = m / n;
            }
        }
        System.out.println("" + ((m == 1)?out:m));
    }
}

См. Программу. И вы поймете алгоритм. Это очень легко и очень быстро. И верните правильный ответ 6857.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...