私は基本的なJava試験のために過去の試験論文を練習していますが、数値が素数であるかどうかをテストするためのforループを作成するのは難しいと感じています。少なくとも2桁の数字で機能するような、より大きな数字の効率測定を追加します。
現時点では、n IS素数。
私の問題は、forループ自体と「trueを返す」をどこに置くかで問題が発生していることだと思います。そして、「falseを返す;」...それは私が犯している本当に基本的な間違いだと確信しています...
public boolean isPrime(int n) {
int i;
for (i = 2; i <= n; i++) {
if (n % i == 0) {
return false;
}
}
return true;
}
私が他の場所でstackoverflowの助けを見つけることができなかったのは、同様の質問がより複雑な実装を求めてより効率的な方法を求めていたためです。
for
ループには少し問題があります。そのはず: -
for (i = 2; i < n; i++) // replace `i <= n` with `i < n`
もちろん、n
をn
で割った場合、余りをチェックしたくないでしょう。常に1
を提供します。
実際、条件を次のように変更することで、繰り返しの回数を減らすことさえできます。-i <= n / 2
。 n
は、n
を考慮する場合を除いて、n / 2
より大きい数で除算できないため、まったく考慮する必要はありません。
したがって、for
ループを次のように変更できます。-
for (i = 2; i <= n / 2; i++)
次のようにして、はるかに早く停止し、ループをより速くスキップできます。
public boolean isPrime(long n) {
// fast even test.
if(n > 2 && (n & 1) == 0)
return false;
// only odd factors need to be tested up to n^0.5
for(int i = 3; i * i <= n; i += 2)
if (n % i == 0)
return false;
return true;
}
最後の反復ステップでtrue
が得られるため、i < n
と記述する必要があります。
エラーはi <= n
for (i = 2; i<n; i++){
public class PrimeNumberCheck {
private static int maxNumberToCheck = 100;
public PrimeNumberCheck() {
}
public static void main(String[] args) {
PrimeNumberCheck primeNumberCheck = new PrimeNumberCheck();
for(int ii=0;ii < maxNumberToCheck; ii++) {
boolean isPrimeNumber = primeNumberCheck.isPrime(ii);
System.out.println(ii + " is " + (isPrimeNumber == true ? "prime." : "not prime."));
}
}
private boolean isPrime(int numberToCheck) {
boolean isPrime = true;
if(numberToCheck < 2) {
isPrime = false;
}
for(int ii=2;ii<numberToCheck;ii++) {
if(numberToCheck%ii == 0) {
isPrime = false;
break;
}
}
return isPrime;
}
}
3で割り切れるこのコード番号では、forループコードの初期化がスキップされます。
Forループの反復も3の倍数をスキップします。
private static boolean isPrime(int n) {
if ((n > 2 && (n & 1) == 0) // check is it even
|| n <= 1 //check for -ve
|| (n > 3 && (n % 3 == 0))) { //check for 3 divisiable
return false;
}
int maxLookup = (int) Math.sqrt(n);
for (int i = 3; (i+2) <= maxLookup; i = i + 6) {
if (n % (i+2) == 0 || n % (i+4) == 0) {
return false;
}
}
return true;
}
最速の方法の1つは、nの平方根までループすることです。
private static boolean isPrime(int n){
int square = (int)Math.ceil((Math.sqrt(n)));//find the square root
HashSet<Integer> nos = new HashSet<>();
for(int i=1;i<=square;i++){
if(n%i==0){
if(n/i==i){
nos.add(i);
}else{
nos.add(i);
int rem = n/i;
nos.add(rem);
}
}
}
return nos.size()==2;//if contains 1 and n then prime
}
Forループでこれにいくつかの簡単なMathプロパティを使用することもできます。
数字「n」は、それ自体または1で割り切れる場合にのみ素数になります。数字が素数でない場合、2つの要素があります。
n = a * b
forループを使用して、「n」に到達する代わりに、番号「n」のsqrtまでチェックできます。 「a」と「b」の両方が数値「n」のsqrtよりも大きい場合、a * bは「n」よりも大きくなります。したがって、少なくとも1つの係数は平方根以下でなければなりません。
ループは次のようになります。
for(int i=2; i<=Math.sqrt(n); i++)
これを行うことにより、コードの実行時の複雑さを大幅に減らすことができます。 O(n/2)になると思います。
それをJava 8の方法で行うと、よりきれいになります
private static boolean isPrimeA(final int number) {
return IntStream
.rangeClosed(2, number/2)
.noneMatch(i -> number%i == 0);
}
_i<=n
_をチェックしているので、_i==n
_の場合、0のみを取得し、常にfalseを返します。i<=(n/2)
を試してください。_i<n
_までチェックする必要はありません。
さて、forループには問題があります。コードは次のとおりです。
public static boolean checkPrimeNUmber(int number)
{
if(number <= 1)
{
return false;
}
for(int a = 2; a < Math.sqrt(number); a++)
{
if(number % a == 0)
{
return false;
}
}
return true;
}
上記のアルゴリズムは1を素数として扱いますが、そうではありません。したがって、ここに解決策があります。
static boolean isPrime(int n) {
int perfect_modulo = 0;
boolean prime = false;
for ( int i = 1; i <= n; i++ ) {
if ( n % i == 0 ) {
perfect_modulo += 1;
}
}
if ( perfect_modulo == 2 ) {
prime = true;
}
return prime;
}