Javaでは多倍長(無限精度)の整数や小数の計算ができます。
小数の割り算については丸めモードを指定する必要があります。丸めモードには次のものがあります。
ROUND_UP 切上げです。絶対値の大きい方に丸めます。ROUND_DOWN 切捨てです。ゼロに近い方に丸めます。ROUND_CEILING 大きい方に丸めます。ROUND_FLOOR 小さい方に丸めます。ROUND_HALF_UP 四捨五入です。最も近い整数が二つあれば,絶対値の大きい方に丸めます。ROUND_HALF_DOWN 四捨五入の変形です。最も近い整数が二つあれば,ゼロに近い方に丸めます。ROUND_HALF_EVEN 標準的な丸め方です。最も近い整数が二つあれば,末位が偶数になる方に丸めます。ROUND_UNNECESSARY これは丸められては困るときに指定します(デフォルトの挙動)。与えられた精度で正確に表せない場合は ArithmeticException が投げられます。日本の四捨五入は 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