• ベストアンサー

ゴールドバッハの予想について・・・

 ゴールドバッハの予想(4以上の任意の偶数は,2つの素数の和で表せる)を表すJavaプログラムを作りたいのですが、できるだけ計算経過時間を短縮したいんです。  下のプログラムを改善して、計算経過時間が速くなるようにして下さい。  どういう理由で改善したのかも付け加えてくれると嬉しいです。 -------------------------------------------------------------------------------------------------------------------------------- public class Gold { static int prime(int number){ int count=0; for(int i=1; i<=number; i++){ if(number%i==0) count++; } return count; } public static void main(String[] args) { long start = System.currentTimeMillis(); int n, p; for(n=4; n<100000; n+=2){ for(p=2; p<n; p++){ if(prime(p)==2 && prime(n-p)==2){ System.out.println(n + "=" + p + "+" + (n-p)); break; } } if(p==n){ System.out.println("この予想は間違いと判明!"); break; } if(n%1000==0){ long stop = System.currentTimeMillis(); System.out.println(n + " " + (stop-start)); } } } } --------------------------------------------------------------------------------------------------------------------------------

noname#171599
noname#171599
  • Java
  • 回答数2
  • ありがとう数1

質問者が選んだベストアンサー

  • ベストアンサー
  • tatsumi01
  • ベストアンサー率30% (976/3185)
回答No.1

Java は良くわからないので外しているかも知れませんが。 (1) 対象を 4 以上の偶数ではなく、6 以上の偶数にすると良いでしょう。4=2+2 は別に示す すると素数は奇数だけですから、for(int i=1; i<=number; i++){ のところが二つ飛ばしにできます。 (2) for(int i=1; i<=number; i++){ のループ、number まで回しているのがムダ 素数判定は 2 以上、√number 以下の整数で割り切れば素数でないのでループの上限は√number で良い number まで回す必要はなく、i で割り切れた時点で prime=1 として飛び出せばよい ループを回り終わっても割り切れていなければ prime=2 で出る 素数判定はもっと高速な方法があると思いますが、とりあえずこれで。

noname#171599
質問者

お礼

わざわざアリガトウございます♪ほんとに助かります(^o^) 申し訳ないんですけど、もし良かったら、実際にJavaで書くとどうなるのかも示してくれませんか??

その他の回答 (1)

  • PecoPlus
  • ベストアンサー率76% (144/188)
回答No.2

 こんばんは。  きっと探せば、すごい最速のアルゴリズムとかあると思いますが、自分の頭で考えられる程度の最適化ですが・・・。  素数は、自分と1以外では割り切れない数となっていますが、もっと、効率よく考えると、まず奇数であり、自分より小さいすべての素数で、割り切れない数といえます。  素数の和であらわせるかというところで素数が必要で、ある数が素数であるかというところでまた素数が必要となります。  そういったところから、何度も何度も同じ数を素数かどうか判別するよりも、いったん判別した素数をキャッシュしておいたほうがよいと考えました。  それがこのクラスです。 -- PrimeCache.java -- import java.util.*; public class PrimeCache implements Iterable<Integer> {   private ArrayList<Integer> list;      public PrimeCache() {     list = new ArrayList<Integer>();     list.add(3);   }      //素数かどうか判定するメソッド   public boolean isPrime(int n) {     if (n % 2 == 0) {       return false;     }          Iterator<Integer> iterator = iterator();     int prime;     while ((prime = iterator.next()) < n) {       if (n % prime == 0) {         return false;       }     }     return true;   }      //素数を昇順にアクセスできるイテレータを発行するメソッド   public Iterator<Integer> iterator() {     return new PrimeIterator();   }      private void addPrime() {     int lastPrime = list.get(list.size() - 1);     int i = lastPrime + 2;     while (true) {       if (pIsPrime(i)) {         list.add(i);         return;       }              i += 2;     }   }      private boolean pIsPrime(int n) {     if (n % 2 == 0) {       return false;     }          for (int p : list) {       if (n % p == 0) {         return false;       }     }          return true;   }      //イテレータ   //素数がキャッシュにあれば、それを返し、なければ、次の素数を探し、   //それを返すと同時にキャッシュに登録する。   private class PrimeIterator implements Iterator<Integer> {     private int index = 0;          public boolean hasNext() {       return true;     }          public Integer next() {       while (index > list.size() - 1) {         addPrime();       }              Integer prime = list.get(index);       index++;       return prime;     }          public void remove() {       throw new UnsupportedOperationException();     }   } } --------------------  このPrimeCacheクラスを使った新しいGoldTestクラスがこれです。 -- GoldTest.java -- import java.util.*; public class GoldTest {   private PrimeCache pCache;      public static void main(String[] args) {     GoldTest gold = new GoldTest();     long start = System.currentTimeMillis();     if (gold.verify(100000)) {       System.out.println("OK");     }     else {       System.out.println("この予想は間違いと判明!");     }     System.out.println(System.currentTimeMillis() - start);   }      public GoldTest() {     pCache = new PrimeCache();   }      public boolean verify(int max) {     for (int n = 4; n < max; n += 2) {       if (!isPrimeSum(n)) {         return false;       }     }     return true;   }      //素数の和で表せるか判定するメソッド   private boolean isPrimeSum(int n) {     Iterator<Integer> iterator = pCache.iterator();     int prime;     while ((prime = iterator.next()) < n) {       if (pCache.isPrime(n - prime)) {         //System.out.println(n + " = " + prime + " + " + (n - prime));         return true;       }     }     return false;   } } -------------------------  100000を検証するのに15秒くらいになりました。  どうでしょう?

関連するQ&A

  • ゴールドバッハの予想についてのプログラムなんですが・・・

     ゴールドバッハの予想(4以上の任意の偶数は,2つの素数の和で表せる)を表すJavaプログラムです。 ---------------------------------------------------------------- public class Gold { static int prime(int number){ int count=0; for(int i=1; i<=number; i+=2){ if(number%i==0) count++; } return count; } public static void main(String[] args) { long start = System.currentTimeMillis(); int n, p; //System.out.println("4=2+2"); for(n=6; n<100000; n+=2){ for(p=2; p<n; p++){ if(prime(p)==2 && prime(n-p)==2){ //System.out.println(n + "=" + p + "+" + (n-p)); break; } } if(p==n){ //System.out.println("この予想は間違いと判明!"); break; } if(n%1000==0){ long stop = System.currentTimeMillis(); System.out.println(n + " " + (stop-start)); } } } } ---------------------------------------------------------------- 『for(int i=1; i<=number; i++){ のループ、number まで回しているのが無駄である。素数判定は 2 以上、√number 以下の整数で割り切れれば素数でないのでループの上限は√number で良い。number まで回す必要はなく、i で割り切れた時点で prime=1 として 飛び出せばよい。ループを回り終わっても割り切れていなければ prime=2 で出る。』というコメントを、上に書いたプログラムを変更して表すにはどうしたら良いのですか?? 誰か教えて下さい(*_*) お願いします★

    • ベストアンサー
    • Java
  • プログラムの違いを教えて下さい・・・

    public class Gold1 { static int prime(int number){ int count=0; for(int i=2; i<number; i+=2){ if(number%i==0) count++; } return count; } public static void main(String[] args) { long start = System.currentTimeMillis(); int n, p; //System.out.println("4=2+2"); for(n=6; n<=100000; n+=2){ for(p=2; p<n; p++){ if(prime(p)==2 && prime(n-p)==2){ //System.out.println(n + "=" + p + "+" + (n-p)); break; } } if(p==n){ //System.out.println("この予想は間違いと判明!"); break; } if(n%1000==0){ long stop = System.currentTimeMillis(); System.out.println(n + " " + (stop-start)); } } } } ---------------------------------------------------------------- この上のプログラムの一部を ---------------------------------------------------------------- if(prime(p)==0 && prime(n-p)==0){ //System.out.println(n + "=" + p + "+" + (n-p)); break; } ---------------------------------------------------------------- というふうに変えたらどういう意味があるのですか??

    • ベストアンサー
    • Java
  • JAVAで素数判定

    JAVAの勉強をしてます 練習問題で、素数判定のプログラムをしているのですが。 1~14までの判定はうまくいきますが、15の判定の時に素数であると表示されて困ってます。どなたかわかりませんか? //読み込んだ数字 n が 15 の場合 if(n == 1) System.out.println("素数ではありません。"); if(n == 2) System.out.println("素数です。"); for (int i = 2; i < n; i++) { if (n % i == 0) { System.out.println("素数ではありません。"); break; } else { System.out.println("素数です。"); break; } } --結果---------------------------------------------- 素数です

    • ベストアンサー
    • Java
  • 以下の問題の式について教えてください。

    以下についてご教示願います。 class Calculator { public int count = 0; public void calc(int n, int p) { count++; if (p>n) return; for (int i=0; i<n; i++) { calc(n, p+1); } } } // int nは、キーボードからの入力 Calculator c = new Calculator(); c.calc(n, 0); System.out.println(c.count); この時、出力されるc.countはどのくらいですか? nを用いた式で表してください。

    • ベストアンサー
    • Java
  • JAVAのfor文で困っています。

    JAVAの勉強をしていますが、本の練習問題でわからなくて困っています。for文で以下の処理を行いたいです(do,whileはなしです)が、 *を5個ごとに改行したいのですが、改行してくれません。 問題の部分↓ if (n % 5 == 0) System.out.println(); 何か良い方法はありませんか?お願いします。 ------------------------------------------------- //(数を読み込んで)だ個数だけ * を5個ごと改行しながら表示 int n = 0; for (int i = n; n <= 0;){ System.out.print("何個*を表示しますか : "); n = stdIn.nextInt(); } for (int i = 1; i <= n; i++){ System.out.print("*"); if (n % 5 == 0) System.out.println(); } ------------------------------------------------

    • ベストアンサー
    • Java
  • javaの二次元配列について質問です

    配列上にあるただ一つの1を入力に応じて移動させるプログラムを作っています。 たとえば0が入力されたら 0, 0, 0 0, 1, 0 0, 1, 0 → 0, 0, 0 0, 0, 0 0, 0, 0 という風に移動させ、端に行ったら移動できないようにしたいです。 今書いたプログラムだと、最初にある1が残ったままになってしまいます。 int[] p = {-1, -1}; int[][] im = new int[3][3]; Scanner scn = new Scanner(System.in); for (int i = 0; i < p.length; i++) { p[i] = 1; } im[p[0]][p[1]] = 1; for (int i = 0; i < im.length; i++) { for (int j = 0; j < im[i].length; j++) { System.out.print(im[i][j] + ","); } System.out.println(); } int n = 0; n = scn.nextInt(); if (n == 0) { p[0] -= 1; } else if (n == 1) { p[1] += 1; } else if (n == 2) { p[0] += 1; } else if (n == 3) { p[1] -= 1; } im[p[0]][p[1]] = 1; for (int i = 0; i < im.length; i++) { for (int j = 0; j < im[i].length; j++) { System.out.print(im[i][j] + ","); } System.out.println(); }

  • 専門学校で情報処理の勉強しております。自宅のパソコンが故障しており使用

    専門学校で情報処理の勉強しております。自宅のパソコンが故障しており使用不可能です。実際にプログラムを動かすことが一番なのですが、、大変申し訳ございませんが有識者の方ご教授お願い致します。Q1 class Calculator { public int count = 0; public void calc(int n, int p) { count++; if (p>n) return; for (int i=0; i<n; i++) { calc(n, p+1); } } } // int nは、キーボードからの入力 Calculator c = new Calculator(); c.calc(n, 0); System.out.println(c.count); この時、出力されるc.countはどのくらいですか? nを用いた式で表現しては頂けませんでしょうか

    • ベストアンサー
    • Java
  • javaプログラミングについて

    ただいまjavaプログラム勉強中でhit&blowを制作しております。 public static void main(String[] args) { Scanner scan = new Scanner(System.in); Random rand = new Random(); int[] answer = new int[4]; int[] input = new int[4]; int[] Number = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, }; int x = 10; for (int i = 0; i < 4; i++) { int select = (int) (Math.random() * x); answer[i] = Number[select]; Number[select] = Number[x - 1]; x--; } int count = 1; while (true) { System.out.println("4桁の異なる数値を入力"); int str_input = scan.nextInt(); // 代入 for (int i = 0; i < 4; i++) { input[i] = str_input; } // hit int hit = 0; for (int i = 0; i < 4; i++) { if (input[i] == answer[i]) { hit++; } } // blow int blow = 0; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++){ if (i != j && input[i] == answer[j]) { blow++; } } } if (hit == 4) { System.out.println("4hit"); System.out.println("正解まで " + count + "回"); break; } else { System.out.println("Hit:" + hit + " Blow:" + (blow - hit)); count++; } } } } 数字が4桁で作っているのですが、数字や4桁以上を入力してしまった場合の表示は後にしようとして、先にhitとblowの判定を作ろうとしているのですが、上記で実行したところhitとblowの判定がされずhit:0blow:0と表示されてしまいます。解決策を教えてください。 自分で作ってみたものの、hit blowの判定方法があっているかも自信がないです。

    • ベストアンサー
    • Java
  • 【JAVA】数字をひし形に出力するプログラムについ

    JAVAについて質問です。 import java.util.Scanner; public class Test { public static void main(String[] args) { Scanner in = new Scanner(System.in); int n = in.nextInt(); int count = 1, space = 0; for (int i = 1; i < 2 * n; i++) { if (i <= n) { space++; } else { space--; } for (int spc = n - space; spc > 0; spc--) { System.out.print(" "); } for (int j = 0; j < count; j++) { System.out.print(i); } if (i < n) { count = count + 2; } else { count = count - 2; } System.out.println(); } in.close(); } } ↑のプログラムで標準入力に例えば8と入力すると、 _______1↵ ______222↵ _____33333↵ ____4444444↵ ___555555555↵ __66666666666↵ _7777777777777↵ 888888888888888↵ _9999999999999↵ __1010101010101010101010↵ ___111111111111111111↵ ____12121212121212↵ _____1313131313↵ ______141414↵ _______ 15↵ という風なひし形が出力されます。 「_」は実際には出力されません。 これを _______1↵ ______222↵ _____33333↵ ____4444444↵ ___555555555↵ __66666666666↵ _7777777777777↵ 888888888888888↵ _9999999999999↵ __00000000000↵ ___111111111↵ ____2222222↵ _____33333↵ ______444↵ _______5↵ という風にしたいです。 (上から10段目以降は1の位が出力されるようにしたいのです) それにはこのプログラムをどう修正すればよいでしょうか?

    • ベストアンサー
    • Java
  • フローチャートが作れず、困っています

    下のjavaソースコードのフローチャートを作りたいのですがわかりません。誰か教えてください。 import java.io.*; public class Sosuu { public static void main(String[] args) throws IOException { BufferedReader buf = new BufferedReader(new InputStreamReader(System.in)); System.out.println("いくつまでの素数を表示するか入力してください"); try{ Prime prm = new Prime(Integer.parseInt(buf.readLine())); prm.calc(); }catch(NumberFormatException e){ System.out.println("数字を入力してください"); } } } class Prime { int endNum; public Prime(int endNum){ this.endNum = endNum; } public void calc(){ if(endNum <= 2){ System.out.println("2以上の数値を入力してください"); return; } for(int i = 2; i <= endNum; i++){ for(int k = 2; k <= i; k++){ if(k == i) System.out.println(Integer.toString(i)); else if((i % k) == 0) break; } } } }

専門家に質問してみよう