0

数値 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 に答える 4

4

コードには重大な問題がかなりあるので、より完全な解決策を示したいと思います。主な問題は、入力検証がないことです! 良いコードは、拒否しないすべての入力で正しくなければなりません。そのため、入力の適切な読み取りと検証を含めました。このようにして、問題を自動的にキャッチできます。

すべての主要な型には適切な名前が必要です! そこで、typedef uint_type を導入しました。コンパイラは、入力 60085147514 が有効かどうかも、コンパイル時に既に確認します (ただし、これも実行時に拒否されます)。コンパイラが警告する場合は、より大きな整数型を使用する必要があります。ただし、すべての一般的な 64 ビット プラットフォームでは unsigned long で十分です (ただし、一般的な 32 ビット プラットフォームではそうではありません)。より大きな整数型が必要な場合は、1 か所だけ変更する必要があります。

あなたのアルゴリズムはひどく非効率的です! 必要なのは、見つかったすべての因数で (可能な限り) 数値を除算することだけであり、素数のみに遭遇することが保証されているため、それを確認する必要はありません。また、入力の平方根までの要因を考慮するだけで済みます。これには、ちょっとしたロジックが必要です。コードを参照してください。

次に、コードは局所性の原則に違反します。変数は、他の場所ではなく、必要な場所で宣言します。C++ 以外のヘッダーも含めましたが、これはさらに必要ありませんでした。using ディレクティブを使用すると、コードが難読化されるだけです。コンポーネントがどこから来たのかわかりません。そしてそれらは必要ありません!より顕著な定義のために、匿名の名前空間も導入しました。

最後に、私はよりコンパクトなコーディング スタイルを使用します (2 つのスペースによるインデント、同じ行にブラケットを使用し、可能であればブラケットを避けます。考えてみてください: この方法では、少しトレーニングすることで、一目で多くのことを確認できます。も読みやすくなっています。

示されているようにコンパイルすると、コンパイラは、未定義で使用される可能性のある maximum_factor について警告します。これは事実ではありません。ここでは、その警告を空と見なすことにしました。

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";
}
于 2011-08-15T09:58:48.820 に答える
4
num = 600851475143;

ここで整数オーバーフローが発生します。のサイズはnum、指定した値を含めるのに十分な大きさではありません。

を使用しuint64_tます。

#include <cstdint>  //must include this!

uint64_t num = 600851475143;

これを読んでください:cstdint

于 2011-08-15T07:11:38.477 に答える
0

そして、修正を提供します。コンパイラによっては、 unsigned long を試して、それが答えを保持できるかどうかを確認できます。cout に書き込んで、変数が期待する値を保持しているかどうかを確認してください。

別の注意事項として、最大の因数を見つけようとしている場合、可能な最大の因数からカウントダウンする方が効率的ではないでしょうか?

于 2011-08-15T07:20:52.013 に答える
0

num変数をlong long intとして宣言できます。

long long int num;

これにより、コードで発生するすべてのタイプのオーバーフローが回避されます!

于 2017-11-29T09:21:32.943 に答える