知恵袋で見つけた「自然数を順番に並べた数」の問題をJavaで解いてみた。

 前回のPythonプログラムJavaに翻訳してみました。(^_^;
 検算用の方が速いようなのでそれを採用しました。(^_^;
 log10がなかったので適当な代替関数を見つけるのにちょっと苦労しました。もともと、桁数を得るためにlog10を使っていたので、BigDecimalのprecision()を使うことにしました。(^_^;
 ちなみに、10^10'0000番目を計算させると明らかにPythonの方がJavaより速いようです。(^_^;
※参考URL
http://stackoverflow.com/questions/15677518/how-to-obtain-the-precision-of-biginteger-in-java
知恵袋で見つけた「自然数を順番に並べた数」の問題をPythonで解いてみた。
チャンパーノウン定数

● Champernowne1.java

/*
 * Champernowne1.java
 * 
 */
 
import java.math.*;

class Champernowne1 {
    static final BigInteger ZERO = BigInteger.ZERO;
    static final BigInteger ONE  = BigInteger.ONE;
    static final BigInteger TEN  = BigInteger.TEN;
    static final BigInteger NINE = new BigInteger("9");
    
    static int NthChampernowne(BigInteger n){
        int i = getDan(n);  // 何段目にあるか調べる
        BigInteger j = NINE.multiply(n).add(TEN.pow(i)).subtract(ONE);
        int k = j.divide(NINE).subtract(ONE).mod(BigInteger.valueOf(i)).intValue();
        return getNum(Ceil2(j,BigInteger.valueOf(9*i)).subtract(ONE),i-1-k);
    }
    
    // 第n段の末項までの項数を求める
    static BigInteger kosDanLst(int n){
        BigInteger x = BigInteger.valueOf(n).multiply(TEN.pow(n));
        BigInteger y = ONE.subtract(TEN.pow(n)).divide(NINE);
        return x.add(y);
    }
    
    // 前からn番目の項が第何段に属するか求める
    static int getDan(BigInteger n){
        if(n.compareTo(ONE)<=0) return 1;
        int    i = 1;
        double j = bIntPrecision(n)-1.0;
        i += (int)Math.floor(j-Math.log10(j));
        if(i<=2) i=1;
        while(kosDanLst(i).compareTo(n)< 0)
            i+=1;
        return i;
    }
    
    static int bIntPrecision(BigInteger bigInt){
        BigDecimal bigDec = new BigDecimal(bigInt);
        return bigDec.precision();
    }
    
    static int getNum(BigInteger x, int n){
        return x.divide(TEN.pow(n)).mod(TEN).intValue();
    }
    
    static BigInteger Ceil2(BigInteger x, BigInteger y){
        BigDecimal bdX = new BigDecimal(x), bdY = new BigDecimal(y);
        return bdX.divide(bdY,0,BigDecimal.ROUND_CEILING).toBigInteger();
    }
    
    public static void main(String[] args) {
        BigInteger m = new BigInteger("1");
        long tm = System.nanoTime();    // Timer Start
        
        for(int i=1; i<=33; i++){
            m = BigInteger.valueOf(i);
            System.out.print(NthChampernowne(m)+" ");
        }
        System.out.println();
        m = BigInteger.valueOf(1000000);
        System.out.println("100万番目の数: "+NthChampernowne(m));
        
        tm=System.nanoTime()-tm;        // Timer Stop
        System.out.printf("Runtime : %.3f [sec]\n",(double)tm/1e9);
    }
}

●実行結果

1 2 3 4 5 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1
100万番目の数: 1
Runtime : 0.006 [sec]

スッキリわかるJava入門 第2版 (スッキリシリーズ)

スッキリわかるJava入門 第2版 (スッキリシリーズ)

スッキリわかる Java入門 実践編 第2版 (スッキリシリーズ)

スッキリわかる Java入門 実践編 第2版 (スッキリシリーズ)