1

これは、Javaでコラッツの予想をシミュレートするために作成したプログラムです。

import java.util.*;
public class Collatz {
public static void main(String args[]){
    Scanner raj= new Scanner(System.in);
    int n;
    int k=0;
    System.out.print("n? ");
    n = raj.nextInt();
    while(n > 1){
        if(n%2 ==1){
            n=3*n+1;
            System.out.println(n);
            k++;
        }
        if(n%2==0){
            n=n/2;
            System.out.println(n);
            k++;
        }

    }
    System.out.print("It took " + k + " iterations!");
}

}

n = 6とすると、

3 10 5 16 8 4 2 1 8回の反復が必要でした!

しかし、たとえばn = 63728127とすると、次のようになります。

191184382 95592191 286776574 143388287 430164862 215082431 645247294 322623647 967870942 483935471 1451806414 725903207 -2117257674 -1058628837 14回の反復が必要でした!

何が悪かったのか?なんで?どうすれば修正できますか?ありがとう!

4

1 に答える 1

4

これは整数オーバーフローの典型的なケースです。プリミティブintは、Javaでは範囲が制限されています。大きな整数を処理する必要がある場合、解決策は常にBigIntegerのようなものを使用することです。

ちなみに、Javaが他のほとんどすべての現代言語のように演算子のオーバーロードをサポートしていれば、事態ははるかに簡単になります。

import java.util.*;
import java.math.BigInteger;


public class Collatz {
    public static void main(String args[]){
        Scanner raj= new Scanner(System.in);
        int k=0;
        System.out.print("n? ");

        BigInteger n = BigInteger.valueOf(raj.nextLong());

        while(n.compareTo(BigInteger.ONE) > 0){
            if(n.testBit(0)){
                n = n.multiply(BigInteger.valueOf(3));
                n = n.add(BigInteger.ONE);
                System.out.println(n);
                k++;
            }
            else {
                n = n.divide(BigInteger.valueOf(2));
                System.out.println(n);
                k++;
            }
        }
        System.out.print("It took " + k + " iterations!");
    }
}
于 2012-08-12T05:55:33.897 に答える