0

テストする数値がハッピー数の場合は1を出力し、それ以外の場合は0を出力するコードを作成しました。

class Ishappy extends Thread {
    private Integer num;
    private Thread main;
    private volatile boolean out = false;

    Ishappy(int i, Thread main) {
        this.main = main;
        num = i;
    }

    void Exit() {
        out = true;
    }

    @Override
    public void run() {
        while(!out && num != 1) {
            if(num == 1) {
                main.interrupt();
                break;
            }

            String s = num.toString();
            int temp = 0;
            for(int i = 0 ; i < s.length(); i++) {
                int x = Integer.parseInt(s.substring(i, i+1));
                temp += x*x;
            }
            num = temp;
        }
    }
}

public class Happy_numbers {
    public static void main(String[] args) {
        byte path[] = null;

        String s = "d:\\data.txt";

        try(FileInputStream fin = new FileInputStream(s)) {
            InputStreamReader in = new InputStreamReader(fin);
            BufferedReader br = new BufferedReader(in);
            s = br.readLine();
            int num;
            while(s != null) {
                num = Integer.parseInt(s);

                Ishappy ishappy = new Ishappy(num,Thread.currentThread()); 
                ishappy.start();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException ex) {
                    System.out.println(1);
                    continue;
                }
                if(ishappy.isAlive()) {
                    ishappy.Exit();
                    System.out.println(0);
                } else
                    System.out.println(11);

                s = br.readLine();
            }
        } catch (FileNotFoundException ex) {
            System.out.println("File not found.");
        }catch(IOException ex){
        }
    }
}

ただし、上記のコードは常にハッピー数に対して11を出力します。これmainは、中断されることはないことを意味します。どうしたの??

data.txtの内容は次のとおりです。

1
7
22

そのうち1と7はハッピー数ですが、22はそうではありません。

4

2 に答える 2

1

私があなたのプログラムを読んでいると、メインループを初めて通過すると、新しいスレッドがset toIsHappyでフォークされます。メソッドの場合、すぐに終了します。 num1IsHappy.run()num1

while(!out && num != 1)

main11スレッドが実行されていないため、スリープしてから印刷します。

if(ishappy.isAlive()) {
    ishappy.Exit();
    System.out.println(0);
} else
   System.out.println(11);

それはあなたが期待するものではありませんか?デバッガの使い方を学ぶべきだと思います。これは、Eclipse でプログラムをデバッグする方法に関する優れたチュートリアルです。

数値7が処理されると、IsHappy.run()メソッドがスピンし、( ) に何度 も設定numされます。その後、それがまだ生きていることを確認し、 を呼び出して出力します。497*7mainIsHappyIsHappy.Exit()0

数値21が処理されると、IsHappy.run()メソッドがスピンし、( ) に何度 も設定numされます。再びスレッドと印刷します。52*2+1*1mainExit()0

だから私はあなたの出力が次のようになると思います:

11
0
0

ループが if の実行を停止するためmain、スレッドが中断されることはありません。whilenum == 1

あなたのコードに関する他のいくつかのコメント。これはテスト コードである可能性があるため、重要ではありませんが、詳しく説明します。

  • 例外をキャッチせずに破棄するだけです(キャッチを参照してくださいIOException)。少なくとも、空の catch ブロックにコメントを入れて、例外を気にしない理由を説明してください。
  • あなたのスレッドは、その計算を実行して回転しています。これは明らかにリソースの有効利用ではありません。
  • 入力ストリームまたはリーダーを閉じていません。これらを扱うときは、常に try/finally を使用してください。
  • Exit()メソッドは小文字で始める必要があります。メソッドのより適切な名前はstop.
于 2012-09-29T23:42:46.430 に答える
0

ここでスレッド化する必要はないと思います。数字の 2 乗の合計が 1 に等しい場合、幸せな数は幸せです。シーケンスに既にテスト済みの数値が含まれている場合。終了するだけです。

ウィキペディアから

n が幸せでない場合、その数列は 1 にはなりません。代わりに、循環に陥ります。

public class Happy_numbers {        
    static int[]SQUARES={0,1,4,9,16,25,36,49,64,81};
    public static boolean is_happy(int n){
        return is_happy(n, new HashSet<Integer>());
    }
    public static boolean is_happy(int n, Collection<Integer> sofar){
        if(n==1) return true;
        else if(sofar.contains(n)) return false;

        sofar.add(n);

        if(n<10) {
            return is_happy(SQUARES[n], sofar);
        }

        char[]digits=String.format("%s", n).toCharArray();
        int s = 0;
        for(char c:digits){
            s+= SQUARES[Integer.valueOf(String.format("%s", c))];
        }

        return is_happy(s, sofar);
    }
    public static void main(String[]args){
        Collection<Integer> c1 = Arrays.asList(
                1, 7, 10, 13, 19, 23, 28, 31, 32, 44, 49, 68, 70, 79, 82, 86, 91, 94, 97, 
                100, 103, 109, 129, 130, 133, 139, 167, 176, 188, 190, 192, 193, 203, 208, 
                219, 226, 230, 236, 239, 262, 263, 280, 291, 293, 301, 302, 310, 313, 319, 
                320, 326, 329, 331, 338, 356, 362, 365, 367, 368, 376, 379, 383, 386, 391, 
                392, 397, 404, 409, 440, 446, 464, 469, 478, 487, 490, 496 );
        Collection<Integer> c2 = new ArrayList<Integer>(c1.size());
        long t = System.currentTimeMillis();
        int c = 1;
        for(int i=0;i<500;i++){
            if(is_happy(i)) {
                System.out.print(i+", ");
                if(c++ % 20 == 0) System.out.println();
                c2.add(i);
            }

        }
        t = System.currentTimeMillis()-t;
        System.out.println("\nTIME : " + t);
        System.out.println("Got them all < 500 : " + (c2.containsAll(c1) && c1.containsAll(c2)));
    }
}

また、マップやキャッシュ技術を使用してさらに改善することもできるため、数値が適切で、以前にこの数値を計算したことがある場合は、同じことを再度行う必要はありません。ウィキペディアより、

500未満のハッピーナンバーは、1、7、10、13、19、23、28、31、32、44、49、68、70、79、82、86、91、94、97、100、103、109です。 , 129, 130, 133, 139, 167, 176, 188, 190, 192, 193, 203, 208, 219, 226, 230, 236, 239, 262, 263, 280, 291, 293, 301, 302, 310 , 313, 319, 320, 326, 329, 331, 338, 356, 362, 365, 367, 368, 376, 379, 383, 386, 391, 392, 397, 404, 409, 440, 446, 464, 469 、478、487、490、496 (OEIS のシーケンス A007770)。

上記のコードでは、500 未満のすべてのハッピー ナンバーを取得するには 435 が必要です。

1, 7, 10, 13, 19, 23, 28, 31, 32, 44, 49, 68, 70, 79, 82, 86, 91, 94, 97, 100, 
103, 109, 129, 130, 133, 139, 167, 176, 188, 190, 192, 193, 203, 208, 219, 226, 230, 236, 239, 262, 
263, 280, 291, 293, 301, 302, 310, 313, 319, 320, 326, 329, 331, 338, 356, 362, 365, 367, 368, 376, 
379, 383, 386, 391, 392, 397, 404, 409, 440, 446, 464, 469, 478, 487, 490, 496, 
TIME : 435
Got them all < 500 : true

そのため、少なくとも現在の数値について、これまでに計算されたものを記憶できるように、コードにいくつかの変更を加えました。

public class Happy_numbers {

    static class Ishappy extends Thread {
        private Integer num;
        private Thread main;
        private volatile boolean out = false;

        private boolean unhappy = false;

        Ishappy(int i, Thread main) {
            this.main = main;
            num = i;
        }

        public boolean isUnhappy() {
            return unhappy;
        }

        void Exit() {
            out = true;
        }

        @Override
        public void run() {
            Set<Integer> sofar = new HashSet<Integer>();
            while(!out && num != 1) {
                unhappy = sofar.contains(num);
                if(num == 1 || unhappy) {
                    main.interrupt();
                    break;
                }

                sofar.add(num);

                String s = num.toString();
                int temp = 0;
                for(int i = 0 ; i < s.length(); i++) {
                    int x = Integer.parseInt(s.substring(i, i+1));
                    temp += x*x;
                }
                num = temp;
            }
        }
    }

    public static void main(String[] args) throws Exception{
        byte path[] = null;

        String s = "./data.txt";

        FileInputStream fin = new FileInputStream(s);
        InputStreamReader in = new InputStreamReader(fin);
        BufferedReader br = new BufferedReader(in);
        int num;
        while((s = br.readLine()) != null) {
            num = Integer.parseInt(s);

            Ishappy ishappy = new Ishappy(num,Thread.currentThread()); 
            ishappy.start();
            ishappy.join();
            if(ishappy.isUnhappy()){
                System.out.println("Number ["+num+"] is not happy");
            }else{
                System.out.println("Number ["+num+"] is happy");
            }
        }
        br.close();
        in.close();
        fin.close();
    }
}

そして出力は

Number [1] is happy
Number [7] is happy
Number [22] is not happy

編集

メインスレッドが中断されない理由がわかりました。

メインの while ループでは、num が 1 であるかどうかを確認します。1 の場合は、num の値をチェックし、それに基づいてメイン スレッドを中断する if 条件に到達しません。

public class Happy_numbers {
    public static void main(String[] args) throws IOException{

        String s = "./data.txt";

        FileInputStream fin = new FileInputStream(s);
        InputStreamReader in = new InputStreamReader(fin);
        BufferedReader br = new BufferedReader(in);
        int num;
        while((s = br.readLine()) != null) {
            num = Integer.parseInt(s);

            Ishappy ishappy = new Ishappy(num,Thread.currentThread()); 
            ishappy.start();
            try {
                Thread.sleep(1000);
            } catch (InterruptedException ex) {
                System.out.println(1);
                continue;   // here is another problem, infinit loop
            }
            if(ishappy.isAlive()) {
                ishappy.Exit();
                System.out.println(0);
            } else
                System.out.println(11);

        }
        br.close();
        in.close();
        fin.close();
        System.out.println("DONE");
    }
}

ここにIhappyクラスがあります

class Ishappy extends Thread {
    private volatile Integer num;
    private Thread main;
    private volatile boolean out = false;

    Ishappy(int i, Thread main) {
        this.main = main;
        num = i;
    }

    void Exit() {
        out = true;
    }

    @Override
    public void run() {
        while(!out) {   /// <- here was the problem
            if(num.intValue() == 1) { // since this condition will break out
                main.interrupt();     // of the loop, you do not need it in the
                break;                // while condition
            }

            String s = num.toString();
            int temp = 0;
            for(int i = 0 ; i < s.length(); i++) {
                int x = Integer.parseInt(s.substring(i, i+1));
                temp += x*x;
            }
            num = temp;
        }
    }
}

そして出力は

1
1
0
DONE
于 2012-09-29T23:58:02.327 に答える