Крупнейший премьер-фактор - C ++ - PullRequest
0 голосов
/ 15 августа 2011

Я пытаюсь найти наибольший простой множитель числа 600851475143. Мой код работает для меньших чисел, которые я тестирую (ниже 100).Однако, когда сталкивается с 600851475143, он возвращает 4370432, определенно не простое.Есть идеи, что может быть не так с моим кодом?

#include <iostream>
#include <time.h>
#include <math.h>

using namespace std;

int main()
{

int num;
int largest;
int count;

cout<<"Please enter a number to have its Largest Prime Factor found"<<endl;
cin>>num;
num = 600851475143;

for (int factor = 1; factor <= num; factor++)
{
    if (num % factor == 0)
    {
        count = 0;
        for (int primetest=2; count == 0 && factor > primetest ; primetest++) 
        {
            if (factor % primetest == 0)
            count ++;    
            //endif
        }
        if (count == 0)
        largest = factor;
        //endif
    }       

}//endif
cout<<largest<<endl;
system("PAUSE");
}

Ответы [ 4 ]

4 голосов
/ 15 августа 2011

Есть довольно много серьезных проблем с кодом, поэтому я хочу показать более полную решение. Основная проблема заключается в том, что он не имеет проверки ввода! Хороший код должен быть правильным на всех входах он не отклоняет. Так что теперь я включил правильное чтение и проверку вход. Таким образом, вы бы автоматически уловили проблему.

Все основные типы должны иметь собственные имена! Итак, я представил typedef uint_type. Компилятор также узнает уже во время компиляции, если ввод 60085147514 допустимо или нет (хотя это сейчас также отклоняется во время выполнения). Если компилятор предупреждает, тогда вам нужно использовать больший целочисленный тип; Однако без знака достаточно на всех общих 64-битные платформы (но не на обычных 32-битных платформах). Если вам нужны большие целочисленные типы, тогда теперь нужно изменить только одно место.

Ваш алгоритм ужасно неэффективен! Все, что нужно, это разделить число на все факторы найдены (как можно дольше), и вы гарантированно встретите только простое цифры - так что проверять это не нужно. А также нужно только учитывать факторы до квадратный корень из ввода. Это все требует немного логики, чтобы продумать - смотрите код.

Тогда ваш код нарушает принцип локальности: объявляйте ваши переменные там, где они есть нужно, а не где-то еще. Вы также включили заголовки не-C ++, которые, кроме того, были не нужно. Использование директив using просто запутывает код: вы больше не видите откуда берутся компоненты; и в них нет необходимости! Я также представил анонимное пространство имен, для более выдающихся определений.

Наконец, я использую более компактный стиль кодирования (отступ на 2 пробела, скобки на та же строка, избегая скобок, если это возможно. Подумайте об этом: таким образом, вы можете увидеть много больше с одного взгляда, хотя, немного потренировавшись, его легче читать.

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

Program LargestPrimeFactor.cpp:
// Compile with
// g++ -O3 -Wall -std=c++98 -pedantic -o LargestPrimeFactor LargestPrimeFactor.cpp

#include <string>
#include <iostream>

namespace {
  const std::string program_name = "LargestPrimeFactor";
  const std::string error_output = "ERROR[" + program_name + "]: ";
  const std::string version_number = "0.1";

  enum ErrorCodes { reading_error = 1, range_error = 2 };
  typedef unsigned long uint_type;
  const uint_type example = 600851475143; // compile-time warnings will show
  // whether uint_type is sufficient
}

int main() {

  uint_type number;
  std::cout << "Please enter a number to have its largest prime factor found:"
   << std::endl;
  std::cin >> number;
  if (not std::cin) {
    std::cerr << error_output << "Number not of the required unsigned integer"
     " type.\n";
    return reading_error;
  }
  if (number <= 1) {
    std::cerr << error_output << "Number " << number << " has no largest prime"
     " factor.\n";
    return range_error;
  }
  const uint_type input = number;

  uint_type largest_factor;
  for (uint_type factor = 2; factor <= number/factor; ++factor)
    if (number % factor == 0) {
      largest_factor = factor;
      do number /= factor; while (number % factor == 0);
    }
  if (number != 1) largest_factor = number;

  std::cout << "The largest prime factor of " << input << " is " << largest_factor
   << ".\n";
}
4 голосов
/ 15 августа 2011
num = 600851475143;

Здесь происходит целочисленное переполнение.Размер num недостаточно велик, чтобы содержать указанное вами значение.

Использовать uint64_t.

#include <cstdint>  //must include this!

uint64_t num = 600851475143;

Читать это: cstdint

0 голосов
/ 29 ноября 2017

Вы можете объявить переменную num как long long int .

long long int num;

Это позволит избежать всех типов переполнений, возникающих в вашем коде!

0 голосов
/ 15 августа 2011

И предложить исправление.В зависимости от вашего компилятора вы можете попробовать unsigned long и посмотреть, сможет ли это удержать ваш ответ.Попробуйте записать в cout и посмотрите, содержит ли переменная ожидаемое вами значение.

С другой стороны, если вы попытаетесь найти самый большой коэффициент *1003*, не будет ли эффективнее вести обратный отсчетот максимально возможного фактора?

...