多倍長計算

Javaでは多倍長(無限精度)の整数や小数の計算ができます。

小数の割り算については丸めモードを指定する必要があります。丸めモードには次のものがあります。

日本の四捨五入は ROUND_HALF_UP に相当しますが,科学技術計算では ROUND_HALF_EVEN が最も標準的です。

例として円周率を好きな桁数だけ求めるプログラムを挙げておきます。

import java.io.*;
import java.math.*;

class Pi {
    public static void main(String[] args) throws IOException {
        BufferedReader br =
            new BufferedReader(new InputStreamReader(System.in));
        System.out.print("桁数? ");  System.out.flush();
        int decimals = Integer.parseInt(br.readLine());
        long time = System.currentTimeMillis();

        BigDecimal two = new BigDecimal("2");
        BigDecimal m25 = new BigDecimal("-25");
        BigDecimal m57121 = new BigDecimal("-57121");

        BigDecimal pi = new BigDecimal("0");
        BigDecimal k = new BigDecimal("1");
        BigDecimal t = new BigDecimal("-80");
        BigDecimal u;
        while (true) {
            t = t.divide(m25, decimals, BigDecimal.ROUND_HALF_EVEN);
            u = t.divide(k, decimals, BigDecimal.ROUND_HALF_EVEN);
            if (u.signum() == 0) break;
            pi = pi.add(u);
            k = k.add(two);
        }
        k = new BigDecimal("1");
        t = new BigDecimal("956");
        while (true) {
            t = t.divide(m57121, decimals, BigDecimal.ROUND_HALF_EVEN);
            u = t.divide(k, decimals, BigDecimal.ROUND_HALF_EVEN);
            if (u.signum() == 0) break;
            pi = pi.add(u);
            k = k.add(two);
        }
        System.out.println(pi);
        System.out.println("時間: " + (System.currentTimeMillis() - time)
                           + "ミリ秒");
    }
}

1997年の時点で,JDK 1.1と486DX2(66MHz)マシンで試したところ,10桁で440ミリ秒,100桁で990ミリ秒,1000桁で7630ミリ秒,10000桁で245740ミリ秒かかりました。

2002年の時点で,J2SDK 1.4とCeleron(500MHz)マシンで試したところ,10桁で25ミリ秒,100桁で43ミリ秒,1000桁で381ミリ秒,10000桁で6950ミリ秒でした。


奥村晴彦

Last modified: 2005-12-26 10:51:15