プログラマー日記

文字コードハンター

みなさん、特殊文字の文字コードで思いつくものをあげてください。いろいろ思い浮かぶかもしれませんが、Shift_JISで0000からffffまでの2バイト文字の文字コードを表示するスクリプトをつくりました。中にはブラウザが解釈できない他言語の文字コードも含まれていますが、みなさんがご存知のあの記号も探してみてください。

ここに文字実体参照記号を表示します。

|

非同盟国への招待状

マナーの悪い登山客である私が大沢の紅葉の写真を見せようと思っていましたがカメラを落としてしまったので急遽別の記事に差し替えます。

<?php
$b = FALSE;
$fp = fopen('/wshounen/counter/alien.log','r');
while(!feof($fp)) {
	$log = fgetcsv($fp,1024,"\t");
	if (strval($log[3])==$_SERVER['REMOTE_ADDR']) {
		$b = TRUE;
	}
}
fclose($fp);
if ($b || (ereg('profiles¥.gang|blogs¥.gang|cult',$_SERVER['HTTP_REFERER'])==1 && ereg('friend1|friend2',$_SERVER['HTTP_REFERER'])!=1)) {
	$log = time()."¥t";
	$url = "http://wshounen.la.coocan.jp".$_SERVER['REQUEST_URI'];
	$log .= $url."¥t";
	$ip = $_SERVER['REMOTE_ADDR'];
	$host = gethostbyaddr($ip);
	$log .= $host."¥t";
	$log .= $ip."¥t";
	$log .= $_SERVER['HTTP_ACCEPT_LANGUAGE']."¥t";
	$log .= $_SERVER['HTTP_USER_AGENT']."¥t";
	$log .= $_SERVER['HTTP_REFERER']."¥r¥n";
	$fp = fopen('/wshounen/counter/alien.log','a');
	flock($fp,LOCK_EX);
	fputs($fp,mb_convert_encoding($log,'UTF-8','AUTO'));
	flock($fp,LOCK_UN);
	fclose($fp);
	include_once '/wshounen/counter/dontcomeagain.php';
	die('<script>history.back();</script>');
}
?>

内緒コメントとかで密告したりして他人のURLを踏ませるとしっかりログ取りしている管理人は密告に気づくんだよ。すると表面的には見えないから風評被害の永享範囲が分からないから全員を処罰するしかないんだよ。会ったことがない相手を信用することって難しいんだぞ。素人プログラマーはすぐこの手のソースコードをうっぷっぷするけどこれはかなりたちの悪いお仕置きだ。私はおぼっちゃまだからおはだかの載ったサイトは一度も開いたことがないけど他人の文句を平然と公開できるような酉頭は1分前に自分が何をしていたかも覚えていねぇだろう。むろん、このソースコードをうっぷっぷすると逮捕される。自分のブログでおかしなことが起こり始めたらまず逃げろ。ブロガーだけに感染する狂犬病ウィルスってのもあるんだよ。感染するとまず水を飲めなくなり幻覚が見え始めやたら噛み付くようになり最終的にはどんな薬も効かずに死ぬんだよ。

|

JAVAを用いた多倍長ライブラリ(永久版)

JAVAを用いた多倍長ライブラリがようやく完成しました。でもこれは始まりでしかないのです。ライブラリには完成はなくそのときの時代に応じて最適化されていくものです。なので、逐次更新できるような仕組みを用意しました。まずはAbstractMathからです。多倍長ライブラリの主計算メソッドを集めてユーザーの好みに合わせてチューニングできるようにしてあります。このクラスを拡張して多倍長ライブラリにします。

多倍長ライブラリ本体であるBigMathです。BigDecimalを使って計算するようになっています。計算可能桁数は現実的に全く制約を感じないくらい多いです。

|

多倍長ライブラリ(更新中)

計算が遅かったり多少の誤差があるのも仕様です。

package jp.wshounen;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
import java.math.RoundingMode;

public class BigMath {
	public static int precision = 20;
	public static MathContext context = new MathContext(24,
			RoundingMode.HALF_EVEN);
	private static BigDecimal ATAN0D1 = null;
	private static BigDecimal ATAN1 = null;
	private static BigDecimal LOG1D1 = null;
	private static BigDecimal LOG2 = null;
	public static BigDecimal PI = pi();
	public static BigDecimal E = e();

	public static BigDecimal round(final BigDecimal in, final int precision) {
		return in.round(new MathContext(precision, RoundingMode.HALF_EVEN));
	}

	public static BigDecimal round(final BigDecimal in) {
		return in.setScale(0, RoundingMode.HALF_EVEN);
	}

	public static BigDecimal degToRad(final BigDecimal arcsec) {
		return arcsec.multiply(ATAN1).divide(new BigDecimal(45), context);
	}

	public static BigDecimal radToDeg(final BigDecimal rad) {
		return rad.multiply(new BigDecimal(45)).divide(ATAN1, context);
	}

	public static BigDecimal floor(final BigDecimal in) {
		return in.setScale(0, RoundingMode.FLOOR);
	}

	public static BigDecimal ceil(final BigDecimal in) {
		return in.setScale(0, RoundingMode.CEILING);
	}

	private static BigDecimal pi() {
		ATAN0D1 = atan0d1();
		ATAN1 = atan(BigDecimal.ONE);
		return shift(ATAN1, 2);
	}

	private static BigDecimal e() {
		LOG1D1 = log1d1();
		LOG2 = log(new BigDecimal(2));
		System.out.println(BigMath.LOG1D1);
		System.out.println(BigMath.LOG2);
		return exp(BigDecimal.ONE);
	}

	public static void setPrecision(final int prec) {
		if (prec >= 20 && prec != precision) {
			precision = prec;
			setContext((int) Math.ceil(Math.log10(prec) * 3) + prec,
					RoundingMode.HALF_EVEN);
		}
	}

	public static void setContext(final int prec, final RoundingMode mode) {
		if (prec > precision && prec != context.getPrecision()) {
			context = new MathContext(prec, mode);
			if (ATAN0D1.precision() < prec) {
				LOG1D1 = null;
				LOG2 = null;
				ATAN0D1 = null;
				ATAN1 = null;
				E = e();
				PI = pi();
			}
		}
	}

	public static BigDecimal shift(final BigDecimal in, final int index) {
		if (index == 0) {
			return in;
		}
		BigInteger bi1 = in.unscaledValue();
		int num = in.scale();
		if (index > 0) {
			return new BigDecimal(bi1.shiftLeft(index), num);
		}
		BigInteger bi2 = bi1.shiftLeft(index);
		bi1 = bi2.shiftRight(index).negate().add(bi1);
		return (bi1.signum() == 0) ? new BigDecimal(bi2, num) : new BigDecimal(
				BigInteger.valueOf(5).pow(-index).multiply(bi1), num - index)
				.stripTrailingZeros().add(new BigDecimal(bi2, num));
	}

	public static BigDecimal shift(final BigDecimal in, final int index,
			final MathContext context) {
		return shift(in, index).plus(context);
	}

	public static BigDecimal asin(final BigDecimal in) {
		int num = in.abs().compareTo(BigDecimal.ONE);
		if (num == 0) {
			return (in.signum() > 0) ? shift(ATAN1, 1) : shift(ATAN1, 1)
					.negate();
		} else if (num == -1) {
			return (in.signum() == 0) ? BigDecimal.ZERO : shift(atan(in.divide(
					sqrt(in.pow(2).negate().add(BigDecimal.ONE)).add(
							BigDecimal.ONE), context)), 1);
		} else if (round(in.abs(), precision).compareTo(BigDecimal.ONE) == 0) {
			return (in.signum() > 0) ? shift(ATAN1, 1) : shift(ATAN1, 1)
					.negate();
		} else {
			return null;
		}
	}

	public static BigDecimal acos(final BigDecimal in) {
		int num = in.abs().compareTo(BigDecimal.ONE);
		if (num == 0) {
			return (in.signum() > 0) ? BigDecimal.ZERO : shift(ATAN1, 2);
		} else if (num == -1) {
			return (in.signum() == 0) ? shift(ATAN1, 1)
					: shift(atan(
							in.divide(
									sqrt(in.pow(2).negate().add(BigDecimal.ONE))
											.add(BigDecimal.ONE), context))
							.negate().add(ATAN1), 1);
		} else if (round(in.abs(), precision).compareTo(BigDecimal.ONE) == 0) {
			return (in.signum() > 0) ? BigDecimal.ZERO : shift(ATAN1, 2);
		} else {
			return null;
		}
	}

	private static BigDecimal atan0d1() {
		if (ATAN0D1 != null) {
			return ATAN0D1.plus();
		}
		BigDecimal bd = BigDecimal.ONE;
		BigDecimal[] temp = new BigDecimal[] { BigDecimal.ONE
				.scaleByPowerOfTen(-1) };
		BigDecimal coef = temp[0].plus();
		do {
			bd = new BigDecimal(2).add(bd);
			coef = coef.scaleByPowerOfTen(-2).negate();
			temp = new BigDecimal[] {
					temp[0].multiply(bd).add(coef).divide(bd, context), temp[0] };
		} while (temp[0].compareTo(temp[1]) != 0);
		return temp[0];
	}

	public static BigDecimal atan(final BigDecimal in) {
		BigDecimal perten = BigDecimal.ONE.scaleByPowerOfTen(-1);
		BigDecimal bd1, bd2, coef;
		BigDecimal[] temp;
		int num = in.signum();
		bd1 = in.abs(context);
		bd2 = BigDecimal.ZERO;
		if (num == 0) {
			return BigDecimal.ZERO;
		} else if (bd1.compareTo(perten) == 0) {
			return (num > 0) ? ATAN0D1.plus() : ATAN0D1.negate();
		} else if (bd1.compareTo(BigDecimal.ONE) == 0 && num == 1
				&& ATAN1 != null) {
			return ATAN1.plus();
		} else if (bd1.compareTo(BigDecimal.ONE) == 1) {
			bd1 = new BigDecimal(-1).add(bd1).divide(bd1.add(BigDecimal.ONE),
					context);
			bd2 = bd2.add(ATAN1);
		}
		perten = perten.negate();
		while (bd1.signum() == 1) {
			bd1 = perten.add(bd1).divide(
					bd1.scaleByPowerOfTen(-1).add(BigDecimal.ONE), context);
			bd2 = bd2.add(ATAN0D1);
		}
		if (num == -1) {
			bd1 = bd1.negate();
			bd2 = bd2.negate();
		}
		coef = bd1.plus();
		temp = new BigDecimal[] { coef.add(bd2, context) };
		bd2 = BigDecimal.ONE;
		bd1 = bd1.pow(2, context).negate();
		do {
			bd2 = new BigDecimal(2).add(bd2);
			coef = coef.multiply(bd1, context);
			temp = new BigDecimal[] {
					temp[0].multiply(bd2).add(coef).divide(bd2, context),
					temp[0] };
		} while (temp[0].compareTo(temp[1]) != 0);
		return temp[0];
	}

	public static BigDecimal root(final BigDecimal in, final int index) {
		BigDecimal bd = in.round(context);
		int num = bd.signum();
		if (num == 0) {
			return BigDecimal.ZERO;
		} else if (num == -1 || index <= 0) {
			return null;
		} else if (bd.compareTo(BigDecimal.ONE) == 0 || index == 1) {
			return bd;
		}
		int i = index;
		while (i % 2 == 0) {
			i /= 2;
			bd = sqrt(bd);
		}
		if (i > 2) {
			bd = pow(bd, BigDecimal.ONE.divide(new BigDecimal(i), context));
		}
		return bd;
	}

	public static BigDecimal sqrt(final BigDecimal in) {
		BigDecimal bd = in.round(context);
		int num = bd.signum();
		if (num == 0) {
			return BigDecimal.ZERO;
		} else if (num == -1) {
			return null;
		} else if (bd.compareTo(BigDecimal.ONE) == 0) {
			return bd;
		}
		BigDecimal[] temp = new BigDecimal[] { bd };
		do {
			temp = new BigDecimal[] {
					temp[0].pow(2).add(bd).divide(shift(temp[0], 1), context),
					temp[0] };
		} while (temp[0].compareTo(temp[1]) != 0);
		return temp[0];
	}

	private static BigDecimal log1d1() {
		if (LOG1D1 != null) {
			return LOG1D1.plus();
		}
		BigDecimal bd = BigDecimal.ONE;
		BigDecimal[] temp = new BigDecimal[] { BigDecimal.ONE
				.scaleByPowerOfTen(-1) };
		BigDecimal coef = temp[0].plus();
		do {
			bd = BigDecimal.ONE.add(bd);
			coef = coef.negate().scaleByPowerOfTen(-1);
			temp = new BigDecimal[] {
					temp[0].multiply(bd).add(coef).divide(bd, context), temp[0] };
		} while (temp[0].compareTo(temp[1]) != 0);
		return temp[0];
	}

	public static BigDecimal log(BigDecimal in) {
		if (in.signum() < 1) {
			return null;
		}
		BigDecimal nperten = new BigDecimal(11).scaleByPowerOfTen(-1);
		BigDecimal bd1 = in.round(context);
		int num = bd1.compareTo(BigDecimal.ONE);
		BigDecimal coef, bd2;
		if (num == 0) {
			return BigDecimal.ZERO;
		} else if (num == -1) {
			coef = BigDecimal.ONE;
		} else {
			bd1 = BigDecimal.ONE.divide(bd1, context);
			coef = new BigDecimal(-1);
		}
		bd2 = BigDecimal.ZERO;
		nperten = new BigDecimal(5).scaleByPowerOfTen(-1);
		while (bd1.compareTo(nperten) == -1) {
			bd1 = shift(bd1, 1);
			bd2 = bd2.add(LOG2);
		}
		if (bd1.plus(context).compareTo(nperten) == 0 && LOG2 != null) {
			return (num > 0) ? bd2.add(LOG2) : bd2.add(LOG2).negate();
		}
		nperten = new BigDecimal(11).scaleByPowerOfTen(-1);
		while (bd1.compareTo(BigDecimal.ONE) == -1) {
			bd1 = bd1.multiply(nperten);
			bd2 = bd2.add(LOG1D1);
		}
		if (num == -1) {
			bd2 = bd2.negate();
		}
		if (bd1.plus(context).compareTo(BigDecimal.ONE) == 0) {
			return bd2;
		}
		bd1 = sqrt(sqrt(bd1));
		coef = shift(coef, 2);
		bd1 = BigDecimal.ONE.add(new BigDecimal(-1).divide(bd1, context));
		coef = coef.multiply(bd1, context);
		BigDecimal[] temp = new BigDecimal[] { coef.add(bd2, context) };
		bd2 = BigDecimal.ONE;
		do {
			bd2 = BigDecimal.ONE.add(bd2);
			coef = coef.multiply(bd1, context);
			temp = new BigDecimal[] {
					temp[0].multiply(bd2).add(coef).divide(bd2, context),
					temp[0] };
		} while (temp[0].compareTo(temp[1]) != 0);
		return temp[0];
	}

	public static BigDecimal sin(final BigDecimal in) {
		BigDecimal bd1, bd2;
		bd2 = shift(ATAN1, 2);
		bd1 = in.remainder(shift(bd2, 1));
		int num = bd1.signum();
		if (num == 0) {
			return BigDecimal.ZERO;
		} else if (num < 0) {
			return sin(bd1.negate()).negate();
		}
		if (bd1.compareTo(bd2) > -1) {
			return sin(bd1.add(bd2)).negate();
		} else if (bd1.compareTo(ATAN1) > 0) {
			if (bd1.compareTo(shift(ATAN1, 1)) > 0) {
				return sin(bd1.negate().add(bd2));
			} else {
				return cos(bd1.negate().add(shift(ATAN1, 1)));
			}
		}
		bd1 = shift(bd1, 1).scaleByPowerOfTen(-1);
		BigDecimal[] temp = new BigDecimal[] { bd1.plus(context) };
		BigDecimal coef = temp[0].plus();
		bd1 = bd1.pow(2, context);
		bd2 = BigDecimal.ZERO;
		do {
			bd2 = new BigDecimal(2).add(bd2);
			coef = coef.multiply(bd1).divide(
					bd2.add(BigDecimal.ONE).multiply(bd2).negate(), context);
			temp = new BigDecimal[] { temp[0].add(coef, context), temp[0] };
		} while (temp[0].compareTo(temp[1]) != 0);
		bd1 = shift(temp[0], 1).pow(2, context);
		return bd1.add(new BigDecimal(-5)).multiply(bd1).add(new BigDecimal(5))
				.multiply(temp[0], context);
	}

	public static BigDecimal cos(final BigDecimal in) {
		BigDecimal bd1, bd2;
		bd2 = shift(ATAN1, 2);
		bd1 = in.remainder(shift(bd2, 1));
		int num = bd1.signum();
		if (num == 0) {
			return BigDecimal.ONE;
		} else if (num < 0) {
			return cos(bd1.negate());
		}
		if (bd1.compareTo(bd2) > -1) {
			return cos(bd1.add(bd2)).negate();
		} else if (bd1.compareTo(ATAN1) > -1) {
			if (bd1.compareTo(shift(ATAN1, 1)) > 0) {
				return cos(bd1.negate().add(bd2)).negate();
			} else {
				return sin(bd1.negate().add(shift(ATAN1, 1)));
			}
		}
		bd1 = shift(bd1, 1).pow(2, context).scaleByPowerOfTen(-2);
		BigDecimal[] temp = new BigDecimal[] { BigDecimal.ONE };
		BigDecimal coef = temp[0].plus();
		bd2 = BigDecimal.ZERO;
		do {
			bd2 = new BigDecimal(2).add(bd2);
			coef = coef.multiply(bd1).divide(
					bd2.negate().add(BigDecimal.ONE).multiply(bd2), context);
			temp = new BigDecimal[] { temp[0].add(coef, context), temp[0] };
		} while (temp[0].compareTo(temp[1]) != 0);
		bd1 = shift(temp[0], 1).pow(2, context);
		return bd1.add(new BigDecimal(-5)).multiply(bd1).add(new BigDecimal(5))
				.multiply(temp[0], context);
	}

	public static BigDecimal tan(final BigDecimal in) {
		BigDecimal bd = cos(in);
		return (bd.signum() == 0) ? null : sin(in).divide(bd, context);
	}

	public static BigDecimal exp(final BigDecimal in) {
		int num = in.signum();
		BigDecimal coef = BigDecimal.ONE;
		BigDecimal bi;
		if (num == 0) {
			return BigDecimal.ONE;
		} else if (num == 1) {
			bi = in.negate(context);
			if (bi.compareTo(LOG1D1.negate()) == 0) {
				return new BigDecimal(11).scaleByPowerOfTen(-1);
			} else if (bi.compareTo(LOG2.negate()) == 0) {
				return new BigDecimal(2);
			}
		} else {
			bi = in.plus(context);
			if (bi.compareTo(LOG1D1.negate()) == 0) {
				return BigDecimal.ONE.divide(new BigDecimal(11), context)
						.scaleByPowerOfTen(1);
			} else if (bi.compareTo(LOG2.negate()) == 0) {
				return new BigDecimal(5).scaleByPowerOfTen(-1);
			}
		}
		if (bi.compareTo(new BigDecimal(-1)) != 0) {
			while (bi.signum() == -1) {
				bi = bi.add(BigDecimal.ONE);
				coef = coef.multiply(E, context);
			}
		}

		if (num == 1) {
			bi = bi.negate();
		} else {
			coef = BigDecimal.ONE.divide(coef, context);
		}
		BigDecimal[] temp = new BigDecimal[] { coef.round(context) };
		num = 0;
		do {
			num++;
			coef = coef.multiply(bi).divide(new BigDecimal(num), context);
			temp = new BigDecimal[] { temp[0].add(coef, context), temp[0] };
		} while (temp[0].compareTo(temp[1]) != 0);
		return temp[0];
	}

	public static BigDecimal pow(final BigDecimal in, final BigDecimal index) {
		BigDecimal bi = log(in);
		if (bi == null) {
			return null;
		} else {
			return exp(bi.multiply(index));
		}
	}

	/**
	 * Matrix of rotation Z to Y. R1(rad).
	 */
	public static BigDecimal[][] rotX(final BigDecimal rad) {
		BigDecimal Cos = cos(rad);
		BigDecimal Sin = sin(rad);
		return new BigDecimal[][] {
				{ BigDecimal.ONE, BigDecimal.ZERO, BigDecimal.ZERO },
				{ BigDecimal.ZERO, Cos, Sin.negate() },
				{ BigDecimal.ZERO, Sin, Cos } };
	}

	/**
	 * Matrix of rotation X to Z. R2(rad).
	 */
	public static BigDecimal[][] rotY(final BigDecimal rad) {
		BigDecimal Cos = cos(rad);
		BigDecimal Sin = sin(rad);
		return new BigDecimal[][] { { Cos, BigDecimal.ZERO, Sin },
				{ BigDecimal.ZERO, BigDecimal.ONE, BigDecimal.ZERO },
				{ Sin.negate(), BigDecimal.ZERO, Cos } };
	}

	/**
	 * Matrix of rotation Y to X. R3(rad).
	 */
	public static BigDecimal[][] rotZ(final BigDecimal rad) {
		BigDecimal Cos = cos(rad);
		BigDecimal Sin = sin(rad);
		return new BigDecimal[][] { { Cos, Sin.negate(), BigDecimal.ZERO },
				{ Sin, Cos, BigDecimal.ZERO },
				{ BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ONE } };
	}

	/**
	 * Matrix of rotation Y to X. R(rad).
	 */
	public static BigDecimal[][] rot2(final BigDecimal rad) {
		BigDecimal Cos = cos(rad);
		BigDecimal Sin = sin(rad);
		return new BigDecimal[][] { { Cos, Sin.negate() }, { Sin, Cos } };
	}

	/**
	 * Rotation (1,0,0) to A[0] = (x,y,z). Rotation (0,1,0) to A[1] = (x,y,z).
	 * Rotation (0,0,1) to A[2] = (x,y,z). Ar = rotA(A,r).
	 */
	public static BigDecimal[] rotA(final BigDecimal[][] A,
			final BigDecimal[] star) {
		if (star.length != A.length) {
			return null;
		} else {
			for (int i = 1; i < A.length; i++) {
				if (A[i].length != A[0].length) {
					return null;
				}
			}
		}
		BigDecimal[] res = new BigDecimal[A[0].length];
		for (int i = 0; i < A[0].length; i++) {
			res[i] = BigDecimal.ZERO;
			for (int j = 0; j < star.length; j++) {
				res[i] = res[i].add(star[j].multiply(A[j][i]));
			}
		}
		return res;
	}

	/**
	 * AB = (rotA(A,B[0]),rotA(A,B[1]),rotA(A,B[2])).
	 */
	public static BigDecimal[][] rotAB(final BigDecimal[][] A,
			final BigDecimal[][] B) {
		BigDecimal[][] res = new BigDecimal[B.length][];
		for (int i = 0; i < B.length; i++) {
			res[i] = rotA(A, B[i]);
		}
		return res;
	}
}

|

JAVAを用いた多倍長ライブラリ(第2版)

多倍長ライブラリの一部を更新しました。以下の資料をご覧下さい。実際には5乗根の計算と0.2乗の計算は似たような速度でしたが計算桁数の関係で平方根以外は逆数乗で計算しています。

多倍長ライブラリの作り方と高次方程式の解の計算方法

通常の多倍長ライブラリです。回転行列を軸の回転に統一しました。

package jp.wshounen;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;

public class BigMath {
	public static int precision = 20;
	public static MathContext context = new MathContext(24,
			RoundingMode.HALF_EVEN);
	public static BigDecimal PI = atan(BigDecimal.ONE).multiply(
			new BigDecimal(4));
	public static BigDecimal E = exp(BigDecimal.ONE);

	public static BigDecimal round(final BigDecimal in, final int precision) {
		return in.round(new MathContext(precision, RoundingMode.HALF_EVEN));
	}

	public static BigDecimal round(final BigDecimal in) {
		return in.setScale(0, RoundingMode.HALF_EVEN);
	}

	public static BigDecimal degToRad(final BigDecimal arcsec) {
		return arcsec.multiply(PI).divide(new BigDecimal(180), context);
	}

	public static BigDecimal radToDeg(final BigDecimal rad) {
		return rad.multiply(new BigDecimal(180)).divide(PI, context);
	}

	public static BigDecimal floor(final BigDecimal in) {
		return in.setScale(0, RoundingMode.FLOOR);
	}

	public static BigDecimal ceil(final BigDecimal in) {
		return in.setScale(0, RoundingMode.CEILING);
	}

	public static void setPrecision(final int prec) {
		if (prec >= 20 && prec != precision) {
			precision = prec;
			setContext((int) Math.ceil(Math.log10(prec) * 3) + prec,
					RoundingMode.HALF_EVEN);
		}
	}

	public static void setContext(final int prec, final RoundingMode mode) {
		if (prec >= precision && prec != context.getPrecision()) {
			context = new MathContext(prec, mode);
			if (PI.precision() < prec) {
				E = exp(BigDecimal.ONE);
				PI = atan(BigDecimal.ONE).multiply(new BigDecimal(4));
			}
		}
	}

	public static BigDecimal asin(final BigDecimal in) {
		int num = in.abs().compareTo(BigDecimal.ONE);
		if (num == 0) {
			return PI.divide(new BigDecimal(in.signum() * 2));
		} else if (num == -1) {
			BigDecimal bi = atan(in.divide(
					root(in.pow(2).negate().add(BigDecimal.ONE), 2).add(
							BigDecimal.ONE), context));
			return bi.add(bi, context);
		} else if (round(in.abs(), precision).compareTo(BigDecimal.ONE) == 0) {
			return PI.divide(new BigDecimal(in.signum() * 2));
		} else {
			return null;
		}
	}

	public static BigDecimal acos(final BigDecimal in) {
		if (in.round(context).compareTo(BigDecimal.ONE) == 0) {
			return BigDecimal.ZERO;
		}
		BigDecimal bi = asin(in);
		if (bi == null) {
			return bi;
		} else {
			return PI.add(bi.add(bi).negate()).divide(new BigDecimal(2));
		}
	}

	public static BigDecimal atan(final BigDecimal in) {
		int num = in.signum();
		if (num == 0) {
			return BigDecimal.ZERO;
		}
		BigDecimal bd1 = in.abs(context);
		BigDecimal bd2 = BigDecimal.ZERO;
		BigDecimal perfive = new BigDecimal(2).scaleByPowerOfTen(-1);
		if (bd1.compareTo(perfive) == 1) {
			BigDecimal perfiveat = atan(perfive);
			while (bd1.signum() == 1) {
				bd1 = perfive
						.negate()
						.add(bd1)
						.divide(bd1.multiply(perfive).add(BigDecimal.ONE),
								context);
				bd2 = bd2.add(perfiveat);
			}
		}
		if (num == -1) {
			bd1 = bd1.negate();
			bd2 = bd2.negate();
		}
		BigDecimal coef = bd1.plus();
		BigDecimal[] temp = new BigDecimal[] { coef.add(bd2, context) };
		num = 1;
		bd1 = bd1.pow(2, context).negate();
		do {
			num += 2;
			bd2 = new BigDecimal(num);
			coef = coef.multiply(bd1, context);
			temp = new BigDecimal[] {
					temp[0].multiply(bd2).add(coef).divide(bd2, context),
					temp[0] };
		} while (temp[0].compareTo(temp[1]) != 0);
		return temp[0];
	}

	public static BigDecimal root(final BigDecimal in, final int index) {
		BigDecimal bd = in.round(context);
		int num = bd.signum();
		if (num == 0) {
			return BigDecimal.ZERO;
		} else if (num == -1 || index <= 0) {
			return null;
		} else if (bd.compareTo(BigDecimal.ONE) == 0 || index == 1) {
			return bd;
		}
		int i = index;
		while (i % 2 == 0) {
			i /= 2;
			bd = sqrt(bd);
		}
		if (i > 2) {
			bd = pow(bd, BigDecimal.ONE.divide(new BigDecimal(i), context));
		}
		return bd;
	}

	public static BigDecimal sqrt(final BigDecimal in) {
		BigDecimal bd = in.round(context);
		int num = bd.signum();
		if (num == 0) {
			return BigDecimal.ZERO;
		} else if (num == -1) {
			return null;
		} else if (bd.compareTo(BigDecimal.ONE) == 0) {
			return bd;
		}
		BigDecimal[] temp = new BigDecimal[] { bd };
		do {
			temp = new BigDecimal[] {
					temp[0].multiply(temp[0]).add(bd)
							.divide(temp[0].add(temp[0]), context), temp[0] };
		} while (temp[0].compareTo(temp[1]) != 0);
		return temp[0];
	}

	public static BigDecimal log(BigDecimal in) {
		if (in.signum() < 1) {
			return null;
		}
		BigDecimal bd1 = in.round(context);
		int num = bd1.compareTo(BigDecimal.ONE);
		BigDecimal coef, bd2;
		if (num == 0) {
			return BigDecimal.ZERO;
		} else if (num == -1) {
			coef = BigDecimal.ONE;
		} else {
			bd1 = BigDecimal.ONE.divide(bd1, context);
			coef = new BigDecimal(-1);
		}
		bd2 = BigDecimal.ZERO;
		do {
			bd1 = bd1.multiply(E, context);
			bd2 = bd2.add(BigDecimal.ONE);
		} while (bd1.compareTo(BigDecimal.ONE) == -1);
		if (num == -1) {
			bd2 = bd2.negate();
		}
		while (bd1.pow(16).compareTo(E) == 1) {
			bd1 = sqrt(bd1);
			coef = coef.add(coef);
		}
		bd1 = BigDecimal.ONE.add(new BigDecimal(-1).divide(bd1, context));
		coef = coef.multiply(bd1, context);
		BigDecimal[] temp = new BigDecimal[] { coef.add(bd2, context) };
		num = 1;
		do {
			num++;
			coef = coef.multiply(bd1, context);
			bd2 = new BigDecimal(num);
			temp = new BigDecimal[] {
					temp[0].multiply(bd2).add(coef).divide(bd2, context),
					temp[0] };
		} while (temp[0].compareTo(temp[1]) != 0);
		return temp[0];
	}

	public static BigDecimal sin(final BigDecimal in) {
		BigDecimal bd1, bd2;
		bd2 = PI.add(PI);
		bd1 = in.remainder(bd2);
		int num = bd1.signum();
		if (num == 0) {
			return BigDecimal.ZERO;
		} else if (num < 0) {
			return sin(bd1.negate()).negate();
		}
		if (bd1.compareTo(PI) > -1) {
			return sin(bd1.add(PI)).negate();
		} else if (bd1.compareTo(PI.divide(new BigDecimal(4))) > 0) {
			bd2 = PI.divide(new BigDecimal(2));
			if (bd1.compareTo(bd2) > 0) {
				return sin(bd1.negate().add(PI));
			} else {
				return cos(bd1.negate().add(bd2));
			}
		}
		bd1 = bd1.divide(new BigDecimal(3), context);
		BigDecimal[] temp = new BigDecimal[] { bd1.plus() };
		BigDecimal coef = temp[0].plus();
		bd1 = bd1.pow(2, context);
		num = 0;
		do {
			num++;
			coef = coef.multiply(bd1).divide(
					new BigDecimal(-2 * num * (2 * num + 1)), context);
			temp = new BigDecimal[] { temp[0].add(coef, context), temp[0] };
		} while (temp[0].compareTo(temp[1]) != 0);
		return temp[0].multiply(temp[0]).multiply(new BigDecimal(-4))
				.add(new BigDecimal(3)).multiply(temp[0], context);
	}

	public static BigDecimal cos(final BigDecimal in) {
		BigDecimal bd1, bd2;
		bd2 = PI.add(PI);
		bd1 = in.remainder(bd2);
		int num = bd1.signum();
		if (num == 0) {
			return BigDecimal.ONE;
		} else if (num < 0) {
			return cos(bd1.negate());
		}
		if (bd1.compareTo(PI) > -1) {
			return cos(bd1.add(PI)).negate();
		} else if (bd1.compareTo(PI.divide(new BigDecimal(4))) > 0) {
			bd2 = PI.divide(new BigDecimal(2));
			if (bd1.compareTo(bd2) > 0) {
				return cos(bd1.negate().add(PI)).negate();
			} else {
				return sin(bd1.negate().add(bd2));
			}
		}
		bd1 = bd1.pow(2).divide(new BigDecimal(9), context);
		BigDecimal[] temp = new BigDecimal[] { BigDecimal.ONE };
		BigDecimal coef = temp[0].plus();
		num = 0;
		do {
			num++;
			coef = coef.multiply(bd1).divide(
					new BigDecimal(-2 * num * (2 * num - 1)), context);
			temp = new BigDecimal[] { temp[0].add(coef, context), temp[0] };
		} while (temp[0].compareTo(temp[1]) != 0);
		return temp[0].multiply(temp[0]).multiply(new BigDecimal(4))
				.add(new BigDecimal(-3)).multiply(temp[0], context);
	}

	public static BigDecimal tan(final BigDecimal in) {
		BigDecimal bd = cos(in);
		if (bd.add(BigDecimal.ONE, context).compareTo(BigDecimal.ONE) == 0) {
			return null;
		} else {
			return sin(in).divide(bd, context);
		}
	}

	public static BigDecimal exp(final BigDecimal in) {
		int num = in.signum();
		BigDecimal coef = BigDecimal.ONE;
		BigDecimal bi;
		if (num == 0) {
			return BigDecimal.ONE;
		} else if (num == 1) {
			bi = in.negate(context);
		} else {
			bi = in.round(context);
		}
		if (bi.compareTo(new BigDecimal(-1)) != 0) {
			while (bi.signum() == -1) {
				bi = bi.add(BigDecimal.ONE);
				coef = coef.multiply(E, context);
			}
		}

		if (num == 1) {
			bi = bi.negate();
		} else {
			coef = BigDecimal.ONE.divide(coef, context);
		}
		BigDecimal[] temp = new BigDecimal[] { coef.round(context) };
		num = 0;
		do {
			num++;
			coef = coef.multiply(bi).divide(new BigDecimal(num), context);
			temp = new BigDecimal[] { temp[0].add(coef, context), temp[0] };
		} while (temp[0].compareTo(temp[1]) != 0);
		return temp[0];
	}

	public static BigDecimal pow(final BigDecimal in, final BigDecimal index) {
		BigDecimal bi = log(in);
		if (bi == null) {
			return null;
		} else {
			return exp(bi.multiply(index));
		}
	}

	/**
	 * Matrix of rotation Z to Y. R1(rad).
	 */
	public static BigDecimal[][] rotX(final BigDecimal rad) {
		BigDecimal Cos = cos(rad);
		BigDecimal Sin = sin(rad);
		return new BigDecimal[][] {
				{ BigDecimal.ONE, BigDecimal.ZERO, BigDecimal.ZERO },
				{ BigDecimal.ZERO, Cos, Sin.negate() },
				{ BigDecimal.ZERO, Sin, Cos } };
	}

	/**
	 * Matrix of rotation X to Z. R2(rad).
	 */
	public static BigDecimal[][] rotY(final BigDecimal rad) {
		BigDecimal Cos = cos(rad);
		BigDecimal Sin = sin(rad);
		return new BigDecimal[][] { { Cos, BigDecimal.ZERO, Sin },
				{ BigDecimal.ZERO, BigDecimal.ONE, BigDecimal.ZERO },
				{ Sin.negate(), BigDecimal.ZERO, Cos } };
	}

	/**
	 * Matrix of rotation Y to X. R3(rad).
	 */
	public static BigDecimal[][] rotZ(final BigDecimal rad) {
		BigDecimal Cos = cos(rad);
		BigDecimal Sin = sin(rad);
		return new BigDecimal[][] { { Cos, Sin.negate(), BigDecimal.ZERO },
				{ Sin, Cos, BigDecimal.ZERO },
				{ BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ONE } };
	}

	/**
	 * Matrix of rotation Y to X. R(rad).
	 */
	public static BigDecimal[][] rot2(final BigDecimal rad) {
		BigDecimal Cos = cos(rad);
		BigDecimal Sin = sin(rad);
		return new BigDecimal[][] { { Cos, Sin.negate() }, { Sin, Cos } };
	}

	/**
	 * Rotation (1,0,0) to A[0] = (x,y,z). Rotation (0,1,0) to A[1] = (x,y,z).
	 * Rotation (0,0,1) to A[2] = (x,y,z). Ar = rotA(A,r).
	 */
	public static BigDecimal[] rotA(final BigDecimal[][] A,
			final BigDecimal[] star) {
		if (star.length != A.length) {
			return null;
		} else {
			for (int i = 1; i < A.length; i++) {
				if (A[i].length != A[0].length) {
					return null;
				}
			}
		}
		BigDecimal[] res = new BigDecimal[A[0].length];
		for (int i = 0; i < A[0].length; i++) {
			res[i] = BigDecimal.ZERO;
			for (int j = 0; j < star.length; j++) {
				res[i] = res[i].add(star[j].multiply(A[j][i]));
			}
		}
		return res;
	}

	/**
	 * AB = (rotA(A,B[0]),rotA(A,B[1]),rotA(A,B[2])).
	 */
	public static BigDecimal[][] rotAB(final BigDecimal[][] A,
			final BigDecimal[][] B) {
		BigDecimal[][] res = new BigDecimal[B.length][];
		for (int i = 0; i < B.length; i++) {
			res[i] = rotA(A, B[i]);
		}
		return res;
	}
}

暦計算用の定数付き20桁精度のライブラリです。

package jp.wshounen;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.ArrayList;

public class DEMath {
	public static final int precision = 20;
	public final static MathContext context = new MathContext(24,
			RoundingMode.HALF_EVEN);
	public static final BigDecimal au = new BigDecimal(149597870691l)
			.scaleByPowerOfTen(-3);
	public static final BigDecimal emrat = new BigDecimal(8130056)
			.scaleByPowerOfTen(-5);
	public static final BigDecimal clight = new BigDecimal(2997922458l)
			.scaleByPowerOfTen(-4);
	public static final BigDecimal jultimeOfJ2000 = new BigDecimal(2451545);
	public static final BigDecimal equatorialRadius = new BigDecimal(6378137)
			.scaleByPowerOfTen(-3);
	public static final BigDecimal polarRadius = new BigDecimal(6356752)
			.scaleByPowerOfTen(-3);
	public static final BigDecimal solarRadius = new BigDecimal(696000);
	public static final BigDecimal lunarRadius = new BigDecimal(1738091)
			.scaleByPowerOfTen(-3);
	public static final BigDecimal PI = atan(BigDecimal.ONE).multiply(
			new BigDecimal(4));
	public static final BigDecimal E = exp(BigDecimal.ONE);
	public static final BigDecimal[][] icrfRot = rotAB(
			rotAB(rotX(arcsecToRad(new BigDecimal(-68192).scaleByPowerOfTen(-7))),
					rotY(arcsecToRad(new BigDecimal(-166170)
							.scaleByPowerOfTen(-7)))),
			rotZ(arcsecToRad(new BigDecimal(146).scaleByPowerOfTen(-4))));
	public static final BigDecimal obliquityArcsecOfJ2000 = new BigDecimal(
			84381406).scaleByPowerOfTen(-3);

	public static BigDecimal round(final BigDecimal in, final int precision) {
		return in.round(new MathContext(precision, RoundingMode.HALF_EVEN));
	}

	public static long divideToFloor(final long value, final long divisor) {
		long remainder = value % divisor;
		return ((remainder < 0 && divisor > 0) || (remainder > 0 && divisor < 0)) ? (value - remainder)
				/ divisor - 1
				: (value - remainder) / divisor;
	}

	public static BigDecimal round(final BigDecimal in) {
		return in.setScale(0, RoundingMode.HALF_EVEN);
	}

	public static BigDecimal arcsecToRad(final BigDecimal arcsec) {
		return arcsec.multiply(PI).divide(new BigDecimal(648000), context);
	}

	public static BigDecimal radToArcsec(final BigDecimal rad) {
		return rad.multiply(new BigDecimal(648000)).divide(PI, context);
	}

	public static BigDecimal floor(final BigDecimal in) {
		return in.setScale(0, RoundingMode.FLOOR);
	}

	public static BigDecimal ceil(final BigDecimal in) {
		return in.setScale(0, RoundingMode.CEILING);
	}

	public static BigDecimal asin(final BigDecimal in) {
		int num = in.abs().compareTo(BigDecimal.ONE);
		if (num == 0) {
			return PI.divide(new BigDecimal(in.signum() * 2));
		} else if (num == -1) {
			BigDecimal bi = atan(in.divide(
					root(in.pow(2).negate().add(BigDecimal.ONE), 2).add(
							BigDecimal.ONE), context));
			return bi.add(bi, context);
		} else if (round(in.abs(), precision).compareTo(BigDecimal.ONE) == 0) {
			return PI.divide(new BigDecimal(in.signum() * 2));
		} else {
			return null;
		}
	}

	public static BigDecimal acos(final BigDecimal in) {
		if (in.round(context).compareTo(BigDecimal.ONE) == 0) {
			return BigDecimal.ZERO;
		}
		BigDecimal bi = asin(in);
		if (bi == null) {
			return bi;
		} else {
			return PI.add(bi.add(bi).negate()).divide(new BigDecimal(2));
		}
	}

	public static BigDecimal atan(final BigDecimal in) {
		int num = in.signum();
		if (num == 0) {
			return BigDecimal.ZERO;
		}
		BigDecimal bd1 = in.abs(context);
		BigDecimal bd2 = BigDecimal.ZERO;
		BigDecimal perfive = new BigDecimal(2).scaleByPowerOfTen(-1);
		if (bd1.compareTo(perfive) == 1) {
			BigDecimal perfiveat = atan(perfive);
			while (bd1.signum() == 1) {
				bd1 = perfive
						.negate()
						.add(bd1)
						.divide(bd1.multiply(perfive).add(BigDecimal.ONE),
								context);
				bd2 = bd2.add(perfiveat);
			}
		}
		if (num == -1) {
			bd1 = bd1.negate();
			bd2 = bd2.negate();
		}
		BigDecimal coef = bd1.plus();
		BigDecimal[] temp = new BigDecimal[] { coef.add(bd2, context) };
		num = 1;
		bd1 = bd1.pow(2, context).negate();
		do {
			num += 2;
			bd2 = new BigDecimal(num);
			coef = coef.multiply(bd1, context);
			temp = new BigDecimal[] {
					temp[0].multiply(bd2).add(coef).divide(bd2, context),
					temp[0] };
		} while (temp[0].compareTo(temp[1]) != 0);
		return temp[0];
	}

	public static BigDecimal root(final BigDecimal in, final int index) {
		BigDecimal bd = in.round(context);
		int num = bd.signum();
		if (num == 0) {
			return BigDecimal.ZERO;
		} else if (num == -1 || index <= 0) {
			return null;
		} else if (bd.compareTo(BigDecimal.ONE) == 0 || index == 1) {
			return bd;
		}
		int i = index;
		while (i % 2 == 0) {
			i /= 2;
			bd = sqrt(bd);
		}
		if (i > 2) {
			bd = pow(bd, BigDecimal.ONE.divide(new BigDecimal(i), context));
		}
		return bd;
	}

	public static BigDecimal sqrt(final BigDecimal in) {
		BigDecimal bd = in.round(context);
		int num = bd.signum();
		if (num == 0) {
			return BigDecimal.ZERO;
		} else if (num == -1) {
			return null;
		} else if (bd.compareTo(BigDecimal.ONE) == 0) {
			return bd;
		}
		BigDecimal[] temp = new BigDecimal[] { bd };
		do {
			temp = new BigDecimal[] {
					temp[0].multiply(temp[0]).add(bd)
							.divide(temp[0].add(temp[0]), context), temp[0] };
		} while (temp[0].compareTo(temp[1]) != 0);
		return temp[0];
	}

	public static BigDecimal log(BigDecimal in) {
		if (in.signum() < 1) {
			return null;
		}
		BigDecimal bd1 = in.round(context);
		int num = bd1.compareTo(BigDecimal.ONE);
		BigDecimal coef, bd2;
		if (num == 0) {
			return BigDecimal.ZERO;
		} else if (num == -1) {
			coef = BigDecimal.ONE;
		} else {
			bd1 = BigDecimal.ONE.divide(bd1, context);
			coef = new BigDecimal(-1);
		}
		bd2 = BigDecimal.ZERO;
		do {
			bd1 = bd1.multiply(E, context);
			bd2 = bd2.add(BigDecimal.ONE);
		} while (bd1.compareTo(BigDecimal.ONE) == -1);
		if (num == -1) {
			bd2 = bd2.negate();
		}
		while (bd1.pow(16).compareTo(E) == 1) {
			bd1 = sqrt(bd1);
			coef = coef.add(coef);
		}
		bd1 = BigDecimal.ONE.add(new BigDecimal(-1).divide(bd1, context));
		coef = coef.multiply(bd1, context);
		BigDecimal[] temp = new BigDecimal[] { coef.add(bd2, context) };
		num = 1;
		do {
			num++;
			coef = coef.multiply(bd1, context);
			bd2 = new BigDecimal(num);
			temp = new BigDecimal[] {
					temp[0].multiply(bd2).add(coef).divide(bd2, context),
					temp[0] };
		} while (temp[0].compareTo(temp[1]) != 0);
		return temp[0];
	}

	public static BigDecimal sin(final BigDecimal in) {
		BigDecimal bd1, bd2;
		bd2 = PI.add(PI);
		bd1 = in.remainder(bd2);
		int num = bd1.signum();
		if (num == 0) {
			return BigDecimal.ZERO;
		} else if (num < 0) {
			return sin(bd1.negate()).negate();
		}
		if (bd1.compareTo(PI) > -1) {
			return sin(bd1.add(PI)).negate();
		} else if (bd1.compareTo(PI.divide(new BigDecimal(4))) > 0) {
			bd2 = PI.divide(new BigDecimal(2));
			if (bd1.compareTo(bd2) > 0) {
				return sin(bd1.negate().add(PI));
			} else {
				return cos(bd1.negate().add(bd2));
			}
		}
		bd1 = bd1.divide(new BigDecimal(3), context);
		BigDecimal[] temp = new BigDecimal[] { bd1.plus() };
		BigDecimal coef = temp[0].plus();
		bd1 = bd1.pow(2, context);
		num = 0;
		do {
			num++;
			coef = coef.multiply(bd1).divide(
					new BigDecimal(-2 * num * (2 * num + 1)), context);
			temp = new BigDecimal[] { temp[0].add(coef, context), temp[0] };
		} while (temp[0].compareTo(temp[1]) != 0);
		return temp[0].multiply(temp[0]).multiply(new BigDecimal(-4))
				.add(new BigDecimal(3)).multiply(temp[0], context);
	}

	public static BigDecimal cos(final BigDecimal in) {
		BigDecimal bd1, bd2;
		bd2 = PI.add(PI);
		bd1 = in.remainder(bd2);
		int num = bd1.signum();
		if (num == 0) {
			return BigDecimal.ONE;
		} else if (num < 0) {
			return cos(bd1.negate());
		}
		if (bd1.compareTo(PI) > -1) {
			return cos(bd1.add(PI)).negate();
		} else if (bd1.compareTo(PI.divide(new BigDecimal(4))) > 0) {
			bd2 = PI.divide(new BigDecimal(2));
			if (bd1.compareTo(bd2) > 0) {
				return cos(bd1.negate().add(PI)).negate();
			} else {
				return sin(bd1.negate().add(bd2));
			}
		}
		bd1 = bd1.pow(2).divide(new BigDecimal(9), context);
		BigDecimal[] temp = new BigDecimal[] { BigDecimal.ONE };
		BigDecimal coef = temp[0].plus();
		num = 0;
		do {
			num++;
			coef = coef.multiply(bd1).divide(
					new BigDecimal(-2 * num * (2 * num - 1)), context);
			temp = new BigDecimal[] { temp[0].add(coef, context), temp[0] };
		} while (temp[0].compareTo(temp[1]) != 0);
		return temp[0].multiply(temp[0]).multiply(new BigDecimal(4))
				.add(new BigDecimal(-3)).multiply(temp[0], context);
	}

	public static BigDecimal tan(final BigDecimal in) {
		BigDecimal bd = cos(in);
		if (bd.add(BigDecimal.ONE, context).compareTo(BigDecimal.ONE) == 0) {
			return null;
		} else {
			return sin(in).divide(bd, context);
		}
	}

	public static BigDecimal exp(final BigDecimal in) {
		int num = in.signum();
		BigDecimal coef = BigDecimal.ONE;
		BigDecimal bi;
		if (num == 0) {
			return BigDecimal.ONE;
		} else if (num == 1) {
			bi = in.negate(context);
		} else {
			bi = in.round(context);
		}
		if (bi.compareTo(new BigDecimal(-1)) != 0) {
			while (bi.signum() == -1) {
				bi = bi.add(BigDecimal.ONE);
				coef = coef.multiply(E, context);
			}
		}

		if (num == 1) {
			bi = bi.negate();
		} else {
			coef = BigDecimal.ONE.divide(coef, context);
		}
		BigDecimal[] temp = new BigDecimal[] { coef.round(context) };
		num = 0;
		do {
			num++;
			coef = coef.multiply(bi).divide(new BigDecimal(num), context);
			temp = new BigDecimal[] { temp[0].add(coef, context), temp[0] };
		} while (temp[0].compareTo(temp[1]) != 0);
		return temp[0];
	}

	public static BigDecimal pow(final BigDecimal in, final BigDecimal index) {
		BigDecimal bi = log(in);
		if (bi == null) {
			return null;
		} else {
			return exp(bi.multiply(index));
		}
	}

	/**
	 * Matrix of rotation Y to Z. R1(-rad).
	 */
	public static BigDecimal[][] rotX(final BigDecimal rad) {
		BigDecimal Cos = cos(rad);
		BigDecimal Sin = sin(rad);
		return new BigDecimal[][] {
				{ BigDecimal.ONE, BigDecimal.ZERO, BigDecimal.ZERO },
				{ BigDecimal.ZERO, Cos, Sin },
				{ BigDecimal.ZERO, Sin.negate(), Cos } };
	}

	/**
	 * Matrix of rotation X to Z. R2(rad).
	 */
	public static BigDecimal[][] rotY(final BigDecimal rad) {
		BigDecimal Cos = cos(rad);
		BigDecimal Sin = sin(rad);
		return new BigDecimal[][] { { Cos, BigDecimal.ZERO, Sin },
				{ BigDecimal.ZERO, BigDecimal.ONE, BigDecimal.ZERO },
				{ Sin.negate(), BigDecimal.ZERO, Cos } };
	}

	/**
	 * Matrix of rotation X to Y. R3(-rad).
	 */
	public static BigDecimal[][] rotZ(final BigDecimal rad) {
		BigDecimal Cos = cos(rad);
		BigDecimal Sin = sin(rad);
		return new BigDecimal[][] { { Cos, Sin, BigDecimal.ZERO },
				{ Sin.negate(), Cos, BigDecimal.ZERO },
				{ BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ONE } };
	}

	/**
	 * Matrix of rotation X to Y. R(-rad).
	 */
	public static BigDecimal[][] rot2(final BigDecimal rad) {
		BigDecimal Cos = cos(rad);
		BigDecimal Sin = sin(rad);
		return new BigDecimal[][] { { Cos, Sin }, { Sin.negate(), Cos } };
	}

	/**
	 * Rotation (1,0,0) to A[0] = (x,y,z). Rotation (0,1,0) to A[1] = (x,y,z).
	 * Rotation (0,0,1) to A[2] = (x,y,z). Ar = rotA(A,r).
	 */
	public static BigDecimal[] rotA(final BigDecimal[][] A,
			final BigDecimal[] star) {
		if (star.length != A.length) {
			return null;
		} else {
			for (int i = 1; i < A.length; i++) {
				if (A[i].length != A[0].length) {
					return null;
				}
			}
		}
		BigDecimal[] res = new BigDecimal[A[0].length];
		for (int i = 0; i < A[0].length; i++) {
			res[i] = BigDecimal.ZERO;
			for (int j = 0; j < star.length; j++) {
				res[i] = res[i].add(star[j].multiply(A[j][i]));
			}
		}
		return res;
	}

	/**
	 * AB = (rotA(A,B[0]),rotA(A,B[1]),rotA(A,B[2])).
	 */
	public static BigDecimal[][] rotAB(final BigDecimal[][] A,
			final BigDecimal[][] B) {
		BigDecimal[][] res = new BigDecimal[B.length][];
		for (int i = 0; i < B.length; i++) {
			res[i] = rotA(A, B[i]);
		}
		return res;
	}

	public static BigDecimal[] getApproximation(final BigDecimal[] y,
			final BigDecimal unit) {
		if (y == null || y.length == 0) {
			return null;
		} else if (y.length == 1) {
			return new BigDecimal[] { y[0].plus() };
		} else if (unit == null || unit.signum() == 0) {
			return new BigDecimal[] { y[(y.length + 1) / 2].plus() };
		}
		BigDecimal[] res = new BigDecimal[y.length];
		for (int i = 0; i < y.length; i++) {
			res[i] = BigDecimal.ZERO;
		}
		for (int i = 0; i < y.length; i++) {
			ArrayList<BigDecimal> temp = new ArrayList<BigDecimal>(0);
			temp.add(y[i].plus());
			for (int j = 0; j < y.length; j++) {
				if (i != j) {
					BigDecimal dif = new BigDecimal(j - (y.length + 1) / 2)
							.multiply(unit);
					temp.add(0, temp.get(0).multiply(dif));
					for (int k = 1; k < temp.size() - 1; k++) {
						temp.set(k,
								temp.get(k + 1).multiply(dif).add(temp.get(k)));
					}
					dif = new BigDecimal(j - i).multiply(unit);
					for (int k = 0; k < temp.size(); k++) {
						temp.set(k, temp.get(k).divide(dif, DEMath.context));
					}
				}
			}
			for (int j = 0; j < y.length; j++) {
				res[j] = res[j].add(temp.get(j));
			}
		}
		return res;
	}

	public static BigDecimal approximationR(final BigDecimal[] coef,
			final BigDecimal x) {
		if (coef == null || coef.length == 0) {
			return BigDecimal.ZERO;
		} else if (x == null || x.signum() == 0) {
			return coef[0].plus();
		}
		BigDecimal y = coef[coef.length - 1].plus();
		for (int i = coef.length - 2; i >= 0; i--) {
			y = y.multiply(x).add(coef[i]);
		}
		return y;
	}

	public static BigDecimal approximationV(final BigDecimal[] coef,
			final BigDecimal x) {
		if (coef == null || coef.length <= 1) {
			return BigDecimal.ZERO;
		} else if (x == null || x.signum() == 0) {
			return coef[1].plus();
		}
		BigDecimal y = new BigDecimal(coef.length - 1)
				.multiply(coef[coef.length - 1]);
		for (int i = coef.length - 2; i >= 1; i--) {
			y = y.multiply(x).add(new BigDecimal(i).multiply(coef[i]));
		}
		return y;
	}
}

|

JAVAを用いた多倍長ライブラリ

BigDecimalで多倍長計算するライブラリです。

package jp.wshounen;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.ArrayList;

public class BigMath {
	private int precision;
	private MathContext context;
	private BigDecimal pi;
	private BigDecimal e;

	public BigMath(int precision) {
		this.precision = precision;
		context = new MathContext((int) Math.ceil(precision * 1.125),
				RoundingMode.HALF_EVEN);
		pi = null;
		e = null;
	}

	public BigDecimal round(BigDecimal in) {
		return in.round(new MathContext(precision, RoundingMode.HALF_EVEN));
	}

	public BigDecimal floor(BigDecimal in) {
		BigDecimal[] bi = in.divideAndRemainder(BigDecimal.ONE);
		if (bi[1].signum() == -1) {
			return bi[0].add(BigDecimal.ONE.negate());
		} else {
			return bi[0];
		}
	}

	public BigDecimal ceil(BigDecimal in) {
		BigDecimal[] bi = in.divideAndRemainder(BigDecimal.ONE);
		if (bi[1].signum() == 1) {
			return bi[0].add(BigDecimal.ONE);
		} else {
			return bi[0];
		}
	}

	public BigDecimal pi() {
		if (pi == null) {
			pi = atan(BigDecimal.ONE).multiply(new BigDecimal(4), context);
		}
		return pi;
	}

	public BigDecimal e() {
		if (e == null) {
			e = exp(BigDecimal.ONE);
		}
		return e;
	}

	public MathContext context() {
		return context;
	}

	public int precision() {
		return precision;
	}

	public BigDecimal asin(BigDecimal in) {
		int num = in.abs().compareTo(BigDecimal.ONE);
		if (num == 0) {
			return pi().divide(new BigDecimal(in.signum() * 2), context);
		} else if (num == -1) {
			BigDecimal bi = atan(in.divide(
					root(in.pow(2).negate().add(BigDecimal.ONE), 2).add(
							BigDecimal.ONE), context));
			return bi.add(bi, context);
		} else if (round(in.abs()).compareTo(BigDecimal.ONE) == 0) {
			return pi().divide(new BigDecimal(in.signum() * 2), context);
		} else {
			return null;
		}
	}

	public BigDecimal acos(BigDecimal in) {
		if (in.round(context).compareTo(BigDecimal.ONE) == 0) {
			return BigDecimal.ZERO;
		}
		BigDecimal bi = asin(in);
		if (bi == null) {
			return bi;
		} else {
			return pi().divide(new BigDecimal(2), context).add(bi.negate(),
					context);
		}
	}

	public BigDecimal atan(BigDecimal in) {
		int num = in.signum();
		if (num == 0) {
			return BigDecimal.ZERO;
		}
		BigDecimal bi = in.abs().round(context);
		BigDecimal res = BigDecimal.ZERO;
		BigDecimal perfive = new BigDecimal("0.2");
		if (bi.compareTo(perfive) == 1) {
			BigDecimal perfiveat = atan(perfive);
			while (bi.signum() == 1) {
				bi = bi.add(perfive.negate()).divide(
						bi.multiply(perfive).add(BigDecimal.ONE), context);
				res = res.add(perfiveat);
			}
		}
		if (num == -1) {
			bi = bi.negate();
			res = res.negate();
		}
		BigDecimal coef = bi.round(context);
		ArrayList<BigDecimal> temp = new ArrayList<BigDecimal>(0);
		temp.add(coef.add(res, context));
		bi = bi.pow(2).negate();
		do {
			num = temp.size();
			coef = coef.multiply(bi, context);
			temp.add(temp.get(num - 1).add(
					coef.divide(new BigDecimal(2 * num + 1), context), context));
		} while (temp.get(num).compareTo(temp.get(num - 1)) != 0);
		return temp.get(num);
	}

	public BigDecimal root(BigDecimal in, int index) {
		int num = in.signum();
		if (num == 0) {
			return BigDecimal.ZERO;
		} else if (num == -1) {
			return null;
		} else if (index <= 0) {
			return null;
		} else if (in.compareTo(BigDecimal.ONE) == 0 || index == 1) {
			return in.round(context);
		}
		BigDecimal bi = in.round(context);
		int i = index * 1;
		int j;
		do {
			j = 2;
			while (i % j != 0 && i > j * j) {
				j++;
			}
			if (i == j * j) {
				j = i;
			} else if (i % j == 0) {
				i = i / j;
			} else {
				j = i;
			}
			if (j > 5) {
				bi = pow(bi, BigDecimal.ONE.divide(new BigDecimal(j), context));
			} else {
				ArrayList<BigDecimal> temp = new ArrayList<BigDecimal>(0);
				temp.add(bi);
				do {
					num = temp.size();
					temp.add(temp
							.get(num - 1)
							.pow(j)
							.multiply(new BigDecimal(j - 1))
							.add(bi)
							.divide(temp.get(num - 1).pow(j - 1)
									.multiply(new BigDecimal(j)), context));
				} while (temp.get(num).compareTo(temp.get(num - 1)) != 0);
				bi = temp.get(num);
			}
		} while (i > j);
		return bi;
	}

	public BigDecimal log(BigDecimal in) {
		if (in.signum() < 1) {
			return null;
		}
		int num = in.compareTo(BigDecimal.ONE);
		BigDecimal coef, bi, res;
		if (num == 0) {
			return BigDecimal.ZERO;
		} else if (num == -1) {
			bi = in.round(context);
			coef = BigDecimal.ONE.negate();
		} else {
			bi = BigDecimal.ONE.divide(in, context);
			coef = BigDecimal.ONE;
		}
		res = BigDecimal.ZERO;
		do {
			bi = bi.multiply(e(), context);
			res = res.add(BigDecimal.ONE);
		} while (bi.compareTo(BigDecimal.ONE) == -1);
		if (bi.pow(5).compareTo(e()) == 1) {
			bi = root(bi, 5);
			coef = coef.multiply(new BigDecimal(5));
		}
		if (num == -1) {
			res = res.negate();
		}
		bi = BigDecimal.ONE.negate().add(BigDecimal.ONE.divide(bi, context));
		coef = coef.multiply(bi, context);
		ArrayList<BigDecimal> temp = new ArrayList<BigDecimal>(0);
		temp.add(coef.add(res, context));
		bi = bi.negate();
		do {
			num = temp.size();
			coef = coef.multiply(bi, context);
			temp.add(temp.get(num - 1).add(
					coef.divide(new BigDecimal(num + 1), context), context));
		} while (temp.get(num).compareTo(temp.get(num - 1)) != 0);
		return temp.get(num);
	}

	public BigDecimal sin(BigDecimal in) {
		BigDecimal[] bi = in.divideAndRemainder(pi(), context);
		bi[1] = bi[1].divide(new BigDecimal(3), context);
		ArrayList<BigDecimal> temp = new ArrayList<BigDecimal>(0);
		if (bi[0].abs().remainder(new BigDecimal(2), context)
				.compareTo(BigDecimal.ONE) == 0) {
			temp.add(bi[1].negate(context));
		} else {
			temp.add(bi[1].round(context));
		}
		BigDecimal coef = temp.get(0);
		bi[1] = bi[1].pow(2);
		int num;
		do {
			num = temp.size();
			coef = coef.multiply(bi[1]).divide(
					new BigDecimal(-2 * num * (2 * num + 1)), context);
			temp.add(temp.get(num - 1).add(coef, context));
		} while (temp.get(num).compareTo(temp.get(num - 1)) != 0);
		bi[1] = temp.get(num).pow(3).negate().multiply(new BigDecimal(4))
				.add(temp.get(num).multiply(new BigDecimal(3)), context);
		num = bi[1].signum();
		return bi[1].add(new BigDecimal(-num), context).add(
				new BigDecimal(num), context);
	}

	public BigDecimal cos(BigDecimal in) {
		BigDecimal[] bi = in.divideAndRemainder(pi(), context);
		bi[1] = bi[1].divide(new BigDecimal(3), context).pow(2);
		ArrayList<BigDecimal> temp = new ArrayList<BigDecimal>(0);
		if (bi[0].abs().remainder(new BigDecimal(2), context)
				.compareTo(BigDecimal.ONE) == 0) {
			temp.add(BigDecimal.ONE.negate());
		} else {
			temp.add(BigDecimal.ONE);
		}
		BigDecimal coef = temp.get(0);
		int num;
		do {
			num = temp.size();
			coef = coef.multiply(bi[1]).divide(
					new BigDecimal(-2 * num * (2 * num - 1)), context);
			temp.add(temp.get(num - 1).add(coef, context));
		} while (temp.get(num).compareTo(temp.get(num - 1)) != 0);
		bi[1] = temp
				.get(num)
				.pow(3)
				.multiply(new BigDecimal(4))
				.add(temp.get(num).negate().multiply(new BigDecimal(3)),
						context);
		num = bi[1].signum();
		return bi[1].add(new BigDecimal(-num), context).add(
				new BigDecimal(num), context);
	}

	public BigDecimal tan(BigDecimal in) {
		BigDecimal bi = cos(in);
		if (bi.add(BigDecimal.ONE, context).compareTo(BigDecimal.ONE) == 0) {
			return null;
		} else {
			return sin(in).divide(bi, context);
		}
	}

	public BigDecimal exp(BigDecimal in) {
		int num = in.signum();
		BigDecimal coef = BigDecimal.ONE;
		BigDecimal bi;
		if (num == 0) {
			return BigDecimal.ONE;
		} else if (num == 1) {
			bi = in.negate(context);
		} else {
			bi = in.round(context);
		}
		if (in.abs().round(context).compareTo(BigDecimal.ONE) != 0) {
			while (bi.signum() == -1) {
				bi = bi.add(BigDecimal.ONE);
				coef = coef.multiply(e(), context);
			}
		}
		if (num == 1) {
			bi = bi.negate();
		} else {
			coef = BigDecimal.ONE.divide(coef, context);
		}
		ArrayList<BigDecimal> temp = new ArrayList<BigDecimal>(0);
		temp.add(coef.round(context));
		do {
			num = temp.size();
			coef = coef.multiply(bi).divide(new BigDecimal(num), context);
			temp.add(temp.get(num - 1).add(coef, context));
		} while (temp.get(num).compareTo(temp.get(num - 1)) != 0);
		return temp.get(num);
	}

	public BigDecimal pow(BigDecimal in, BigDecimal index) {
		BigDecimal bi = log(in);
		if (bi == null) {
			return null;
		} else {
			return exp(bi.multiply(index));
		}
	}
}

暦計算用の20桁精度の定数付きライブラリです。

package jp.wshounen;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.ArrayList;

public class DEMath {
	public final static MathContext context = new MathContext(24,
			RoundingMode.HALF_EVEN);
	public static final int precision = 20;
	public static final BigDecimal au = new BigDecimal(149597870691l)
			.scaleByPowerOfTen(-3);
	public static final BigDecimal emrat = new BigDecimal(8130056)
			.scaleByPowerOfTen(-5);
	public static final BigDecimal clight = new BigDecimal(2997922458l)
			.scaleByPowerOfTen(-4);
	public static final BigDecimal jultimeOfJ2000 = new BigDecimal(2451545);
	public static final BigDecimal equatorialRadius = new BigDecimal(6378137)
			.scaleByPowerOfTen(-3);
	public static final BigDecimal polarRadius = new BigDecimal(6356752)
			.scaleByPowerOfTen(-3);
	public static final BigDecimal solarRadius = new BigDecimal(695989245)
			.scaleByPowerOfTen(-3);
	public static final BigDecimal lunarRadius = new BigDecimal(17380908)
			.scaleByPowerOfTen(-4);
	public static final BigDecimal PI = atan(BigDecimal.ONE).multiply(
			new BigDecimal(4), context);
	public static final BigDecimal E = exp(BigDecimal.ONE);
	public static final BigDecimal[][] icrfRot = rotAB(
			rotAB(rotX(arcsecToRad(new BigDecimal(-68192).scaleByPowerOfTen(-7))),
					rotY(arcsecToRad(new BigDecimal(-166170)
							.scaleByPowerOfTen(-7)))),
			rotZ(arcsecToRad(new BigDecimal(146).scaleByPowerOfTen(-4))));
	public static final BigDecimal obliquityArcsecOfJ2000 = new BigDecimal(
			84381406).scaleByPowerOfTen(-3);

	public static BigDecimal round(final BigDecimal in, final int precision) {
		return in.round(new MathContext(precision, RoundingMode.HALF_EVEN));
	}

	public static long divideToFloor(final long value, final long divisor) {
		long remainder = value % divisor;
		return ((remainder < 0 && divisor > 0) || (remainder > 0 && divisor < 0)) ? (value - remainder)
				/ divisor - 1
				: (value - remainder) / divisor;
	}

	public static BigDecimal round(final BigDecimal in) {
		return in.setScale(0, RoundingMode.HALF_EVEN);
		// BigDecimal[] bi = in.divideAndRemainder(BigDecimal.ONE);
		// int num = bi[1].add(bi[1]).abs().compareTo(BigDecimal.ONE);
		// if (num == 1
		// || (num == 0 && bi[0].remainder(new BigDecimal(2)).signum() != 0)) {
		// return bi[0].add(new BigDecimal(bi[1].signum()));
		// } else {
		// return bi[0];
		// }
	}

	public static BigDecimal arcsecToRad(final BigDecimal arcsec) {
		return arcsec.multiply(PI).divide(new BigDecimal(648000), context);
	}

	public static BigDecimal radToArcsec(final BigDecimal rad) {
		return rad.multiply(new BigDecimal(648000)).divide(PI, context);
	}

	public static BigDecimal floor(final BigDecimal in) {
		return in.setScale(0, RoundingMode.FLOOR);
		// BigDecimal[] bi = in.divideAndRemainder(BigDecimal.ONE);
		// if (bi[1].signum() == -1) {
		// return bi[0].add(BigDecimal.ONE.negate());
		// } else {
		// return bi[0];
		// }
	}

	public static BigDecimal ceil(final BigDecimal in) {
		return in.setScale(0, RoundingMode.CEILING);
		// BigDecimal[] bi = in.divideAndRemainder(BigDecimal.ONE);
		// if (bi[1].signum() == 1) {
		// return bi[0].add(BigDecimal.ONE);
		// } else {
		// return bi[0];
		// }
	}

	public static BigDecimal asin(final BigDecimal in) {
		int num = in.abs().compareTo(BigDecimal.ONE);
		if (num == 0) {
			return PI.divide(new BigDecimal(in.signum() * 2), context);
		} else if (num == -1) {
			BigDecimal bi = atan(in.divide(
					root(in.pow(2).negate().add(BigDecimal.ONE), 2).add(
							BigDecimal.ONE), context));
			return bi.add(bi, context);
		} else if (round(in.abs(), 20).compareTo(BigDecimal.ONE) == 0) {
			return PI.divide(new BigDecimal(in.signum() * 2), context);
		} else {
			return null;
		}
	}

	public static BigDecimal acos(final BigDecimal in) {
		if (in.round(context).compareTo(BigDecimal.ONE) == 0) {
			return BigDecimal.ZERO;
		}
		BigDecimal bi = asin(in);
		if (bi == null) {
			return bi;
		} else {
			return PI.divide(new BigDecimal(2), context).add(bi.negate(),
					context);
		}
	}

	public static BigDecimal atan(final BigDecimal in) {
		int num = in.signum();
		if (num == 0) {
			return BigDecimal.ZERO;
		}
		BigDecimal bi = in.abs().round(context);
		BigDecimal res = BigDecimal.ZERO;
		BigDecimal perfive = new BigDecimal(2).scaleByPowerOfTen(-1);
		if (bi.compareTo(perfive) == 1) {
			BigDecimal perfiveat = atan(perfive);
			while (bi.signum() == 1) {
				bi = bi.add(perfive.negate()).divide(
						bi.multiply(perfive).add(BigDecimal.ONE), context);
				res = res.add(perfiveat);
			}
		}
		if (num == -1) {
			bi = bi.negate();
			res = res.negate();
		}
		BigDecimal coef = bi.round(context);
		ArrayList<BigDecimal> temp = new ArrayList<BigDecimal>(0);
		temp.add(coef.add(res, context));
		bi = bi.pow(2).negate();
		do {
			num = temp.size();
			coef = coef.multiply(bi, context);
			temp.add(temp.get(num - 1).add(
					coef.divide(new BigDecimal(2 * num + 1), context), context));
		} while (temp.get(num).compareTo(temp.get(num - 1)) != 0);
		return temp.get(num);
	}

	public static BigDecimal root(final BigDecimal in, final int index) {
		int num = in.signum();
		if (num == 0) {
			return BigDecimal.ZERO;
		} else if (num == -1) {
			return null;
		} else if (index <= 0) {
			return null;
		} else if (in.compareTo(BigDecimal.ONE) == 0 || index == 1) {
			return in.round(context);
		}
		BigDecimal bi = in.round(context);
		int i = index;
		int j = 2;
		boolean b = true;
		while (i >= j && b) {
			while (i % j != 0 && i > j * j) {
				j++;
			}
			if (i % j == 0) {
				i /= j;
			} else {
				j = i;
				b = false;
			}
			if (j > 5) {
				bi = pow(bi, BigDecimal.ONE.divide(new BigDecimal(j), context));
			} else {
				ArrayList<BigDecimal> temp = new ArrayList<BigDecimal>(0);
				temp.add(bi);
				do {
					num = temp.size();
					temp.add(temp
							.get(num - 1)
							.pow(j)
							.multiply(new BigDecimal(j - 1))
							.add(bi)
							.divide(temp.get(num - 1).pow(j - 1)
									.multiply(new BigDecimal(j)), context));
				} while (temp.get(num).compareTo(temp.get(num - 1)) != 0);
				bi = temp.get(num);
			}
		}
		return bi;
	}

	public static BigDecimal log(final BigDecimal in) {
		if (in.signum() < 1) {
			return null;
		}
		int num = in.compareTo(BigDecimal.ONE);
		BigDecimal coef, bi, res;
		if (num == 0) {
			return BigDecimal.ZERO;
		} else if (num == -1) {
			bi = in.round(context);
			coef = BigDecimal.ONE.negate();
		} else {
			bi = BigDecimal.ONE.divide(in, context);
			coef = BigDecimal.ONE;
		}
		res = BigDecimal.ZERO;
		do {
			bi = bi.multiply(E, context);
			res = res.add(BigDecimal.ONE);
		} while (bi.compareTo(BigDecimal.ONE) == -1);
		if (bi.pow(5).compareTo(E) == 1) {
			bi = root(bi, 5);
			coef = coef.multiply(new BigDecimal(5));
		}
		if (num == -1) {
			res = res.negate();
		}
		bi = BigDecimal.ONE.negate().add(BigDecimal.ONE.divide(bi, context));
		coef = coef.multiply(bi, context);
		ArrayList<BigDecimal> temp = new ArrayList<BigDecimal>(0);
		temp.add(coef.add(res, context));
		bi = bi.negate();
		do {
			num = temp.size();
			coef = coef.multiply(bi, context);
			temp.add(temp.get(num - 1).add(
					coef.divide(new BigDecimal(num + 1), context), context));
		} while (temp.get(num).compareTo(temp.get(num - 1)) != 0);
		return temp.get(num);
	}

	public static BigDecimal sin(final BigDecimal in) {
		BigDecimal[] bi = in.divideAndRemainder(PI, context);
		bi[1] = bi[1].divide(new BigDecimal(3), context);
		ArrayList<BigDecimal> temp = new ArrayList<BigDecimal>(0);
		if (bi[0].abs().remainder(new BigDecimal(2), context)
				.compareTo(BigDecimal.ONE) == 0) {
			temp.add(bi[1].negate(context));
		} else {
			temp.add(bi[1].round(context));
		}
		BigDecimal coef = temp.get(0);
		bi[1] = bi[1].pow(2);
		int num;
		do {
			num = temp.size();
			coef = coef.multiply(bi[1]).divide(
					new BigDecimal(-2 * num * (2 * num + 1)), context);
			temp.add(temp.get(num - 1).add(coef, context));
		} while (temp.get(num).compareTo(temp.get(num - 1)) != 0);
		bi[1] = temp.get(num).pow(3).negate().multiply(new BigDecimal(4))
				.add(temp.get(num).multiply(new BigDecimal(3)), context);
		num = bi[1].signum();
		return bi[1].add(new BigDecimal(-num), context).add(
				new BigDecimal(num), context);
	}

	public static BigDecimal cos(final BigDecimal in) {
		BigDecimal[] bi = in.divideAndRemainder(PI, context);
		bi[1] = bi[1].divide(new BigDecimal(3), context).pow(2);
		ArrayList<BigDecimal> temp = new ArrayList<BigDecimal>(0);
		if (bi[0].abs().remainder(new BigDecimal(2), context)
				.compareTo(BigDecimal.ONE) == 0) {
			temp.add(BigDecimal.ONE.negate());
		} else {
			temp.add(BigDecimal.ONE);
		}
		BigDecimal coef = temp.get(0);
		int num;
		do {
			num = temp.size();
			coef = coef.multiply(bi[1]).divide(
					new BigDecimal(-2 * num * (2 * num - 1)), context);
			temp.add(temp.get(num - 1).add(coef, context));
		} while (temp.get(num).compareTo(temp.get(num - 1)) != 0);
		bi[1] = temp
				.get(num)
				.pow(3)
				.multiply(new BigDecimal(4))
				.add(temp.get(num).negate().multiply(new BigDecimal(3)),
						context);
		num = bi[1].signum();
		return bi[1].add(new BigDecimal(-num), context).add(
				new BigDecimal(num), context);
	}

	public static BigDecimal tan(final BigDecimal in) {
		BigDecimal bi = cos(in);
		if (bi.add(BigDecimal.ONE, context).compareTo(BigDecimal.ONE) == 0) {
			return null;
		} else {
			return sin(in).divide(bi, context);
		}
	}

	public static BigDecimal exp(final BigDecimal in) {
		int num = in.signum();
		BigDecimal coef = BigDecimal.ONE;
		BigDecimal bi;
		if (num == 0) {
			return BigDecimal.ONE;
		} else if (num == 1) {
			bi = in.negate(context);
		} else {
			bi = in.round(context);
		}
		if (in.abs().round(context).compareTo(BigDecimal.ONE) != 0) {
			while (bi.signum() == -1) {
				bi = bi.add(BigDecimal.ONE);
				coef = coef.multiply(E, context);
			}
		}
		if (num == 1) {
			bi = bi.negate();
		} else {
			coef = BigDecimal.ONE.divide(coef, context);
		}
		ArrayList<BigDecimal> temp = new ArrayList<BigDecimal>(0);
		temp.add(coef.round(context));
		do {
			num = temp.size();
			coef = coef.multiply(bi).divide(new BigDecimal(num), context);
			temp.add(temp.get(num - 1).add(coef, context));
		} while (temp.get(num).compareTo(temp.get(num - 1)) != 0);
		return temp.get(num);
	}

	public static BigDecimal pow(final BigDecimal in, final BigDecimal index) {
		BigDecimal bi = log(in);
		if (bi == null) {
			return null;
		} else {
			return exp(bi.multiply(index));
		}
	}

	/**
	 * Matrix of rotation Y to Z. R1(-rad).
	 */
	public static BigDecimal[][] rotX(final BigDecimal rad) {
		BigDecimal Cos = cos(rad);
		BigDecimal Sin = sin(rad);
		return new BigDecimal[][] {
				{ BigDecimal.ONE, BigDecimal.ZERO, BigDecimal.ZERO },
				{ BigDecimal.ZERO, Cos, Sin },
				{ BigDecimal.ZERO, Sin.negate(), Cos } };
	}

	/**
	 * Matrix of rotation X to Z. R2(rad).
	 */
	public static BigDecimal[][] rotY(final BigDecimal rad) {
		BigDecimal Cos = cos(rad);
		BigDecimal Sin = sin(rad);
		return new BigDecimal[][] { { Cos, BigDecimal.ZERO, Sin },
				{ BigDecimal.ZERO, BigDecimal.ONE, BigDecimal.ZERO },
				{ Sin.negate(), BigDecimal.ZERO, Cos } };
	}

	/**
	 * Matrix of rotation X to Y. R3(-rad).
	 */
	public static BigDecimal[][] rotZ(final BigDecimal rad) {
		BigDecimal Cos = cos(rad);
		BigDecimal Sin = sin(rad);
		return new BigDecimal[][] { { Cos, Sin, BigDecimal.ZERO },
				{ Sin.negate(), Cos, BigDecimal.ZERO },
				{ BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ONE } };
	}

	/**
	 * Rotation (1,0,0) to A[0] = (x,y,z). Rotation (0,1,0) to A[1] = (x,y,z).
	 * Rotation (0,0,1) to A[2] = (x,y,z). Ar = rotA(A,r).
	 */
	public static BigDecimal[] rotA(final BigDecimal[][] A,
			final BigDecimal[] star) {
		BigDecimal[] res = new BigDecimal[] { BigDecimal.ZERO, BigDecimal.ZERO,
				BigDecimal.ZERO };
		for (int i = 0; i < 3; i++)
			for (int j = 0; j < 3; j++)
				res[i] = res[i].add(star[j].multiply(A[j][i]));
		return res;
	}

	/**
	 * AB = (rotA(A,B[0]),rotA(A,B[1]),rotA(A,B[2])).
	 */
	public static BigDecimal[][] rotAB(final BigDecimal[][] A,
			final BigDecimal[][] B) {
		return new BigDecimal[][] { rotA(A, B[0]), rotA(A, B[1]), rotA(A, B[2]) };
	}

	public static BigDecimal[] getApproximation(final BigDecimal[] y,
			final BigDecimal unit) {
		if (y == null || y.length == 0) {
			return null;
		} else if (y.length == 1) {
			return new BigDecimal[] { y[0].plus() };
		} else if (unit == null || unit.signum() == 0) {
			return new BigDecimal[] { y[(y.length + 1) / 2].plus() };
		}
		BigDecimal[] res = new BigDecimal[y.length];
		for (int i = 0; i < y.length; i++) {
			res[i] = BigDecimal.ZERO;
		}
		for (int i = 0; i < y.length; i++) {
			ArrayList<BigDecimal> temp = new ArrayList<BigDecimal>(0);
			temp.add(y[i].plus());
			for (int j = 0; j < y.length; j++) {
				if (i != j) {
					BigDecimal dif = new BigDecimal(j - (y.length + 1) / 2)
							.multiply(unit);
					temp.add(0, temp.get(0).multiply(dif));
					for (int k = 1; k < temp.size() - 1; k++) {
						temp.set(k,
								temp.get(k + 1).multiply(dif).add(temp.get(k)));
					}
					dif = new BigDecimal(j - i).multiply(unit);
					for (int k = 0; k < temp.size(); k++) {
						temp.set(k, temp.get(k).divide(dif, DEMath.context));
					}
				}
			}
			for (int j = 0; j < y.length; j++) {
				res[j] = res[j].add(temp.get(j));
			}
		}
		return res;
	}

	public static BigDecimal approximationR(final BigDecimal[] coef,
			final BigDecimal x) {
		if (coef == null || coef.length == 0) {
			return BigDecimal.ZERO;
		} else if (x == null || x.signum() == 0) {
			return coef[0].plus();
		}
		BigDecimal y = coef[coef.length - 1].plus();
		for (int i = coef.length - 2; i >= 0; i--) {
			y = y.multiply(x).add(coef[i]);
		}
		return y;
	}

	public static BigDecimal approximationV(final BigDecimal[] coef,
			final BigDecimal x) {
		if (coef == null || coef.length <= 1) {
			return BigDecimal.ZERO;
		} else if (x == null || x.signum() == 0) {
			return coef[1].plus();
		}
		BigDecimal y = new BigDecimal(coef.length - 1)
				.multiply(coef[coef.length - 1]);
		for (int i = coef.length - 2; i >= 1; i--) {
			y = y.multiply(x).add(new BigDecimal(i).multiply(coef[i]));
		}
		return y;
	}
}

Macintoshで月影図1枚描くのに8分かかるので高速化の作業に入ります。だけどbyte配列の数を使わないといけないような計算はこの世に存在するのか?boolean配列の多倍長ライブラリもつくってみようかと思ったけどboolean配列だと無駄が多すぎて実装も大変なのでやめます。

このソースコードはMITライセンスですが万人に自由に使っていただくためJAVAを用いた多倍長計算の上記の機能の改良版について特許出願することを禁止いたします。

|

月影図を表示します

若くないと感じる時、それは計算の勘が鈍ったとき。最近数ヶ月使わなければすぐプログラミングのやり方を忘れて過去の作品が遺構になったりAndroidのプロジェクトが全部動かなくなったり。何事も日頃の行いがものを言いますね。

デイリーポータルZ

ブログネタ: 【賞品付き】もう若くないと感じた瞬間は?参加数

|

バスは街の探偵団

バスは毎日同じところを走っているけど、いろいろな客が乗ってくるから大変なこともある。最近はバス車内での犯罪に対応するためにいちはやく監視カメラなどを導入されていたりする。バスの管制官は実にいろいろな情報を発信していてきていて飽きない。車内で犯人と被害者が同乗する事もあるしいろいろな状況に対応するために日夜策士のような情報戦がされている。だから、真の地域の防犯の拠点はバスなどの公共交通機関なのだろう。

|

来年の金環日蝕の月縁図のサイト

バスに大学時代の知人にそっくりな人が乗っていてびっくりしました。来年の金環日蝕の際の月縁図です。東京スカイツリーの直下の座標がセットされています。月縁付近を誇張して描いているため外向きに曲がる曲線は太陽の輪郭の一部です。

2012年5月21日の金環食の月縁図(東京スカイツリー直下)

このサイトは日本国内の座標で表示した場合だけ正確な月縁図を表示します。このURLは以下のようになっています。

http://wshounen.la.coocan.jp/20120521/contourImage.php?nd=緯度(度)&ed=経度(度)&ht=標高(m)

児童教育のために別ブログをやっていますが、重要度の高い記事が発生したので公開を一日遅らせます。向こうの記事も大事なのですが、緊急を要する状況ではないためです。自分の力で考えられないような大人のために記事を書くより全世界に貢献する仕事を遂行するための準備をするほうが重要です。

|

あなどれないSNS

Mixioffice

注意:写真は本文とは関係ありません

ブログやSNSで有名な会社2社を見学してきた。C社は受付嬢はいなかったけど近くにいた係員と面談して質問状を受け取って担当部署へ回すと伝えてもらった。M社は社員2名により会議室へ連れ込まれ面談した後、運営委員を通してのお問い合わせしか応じられませんと言われて二度と来るなと追い返された。

大手SNSで背番号のついた携帯電話ではないと会員登録できないサイトがあるためユーザーのクレームに負けて携帯各社はスマートフォンに背番号を導入する動きを活発化させているけど少し考えていただきたい。背番号はブラウザのヘッダー部分を読み取っているだけなので不正サイトでヘッダーを回収して不正なブラウザで不当請求サイトを悪意のある人が閲覧すれば簡単に見ていないサイトの不当請求ができてしまう危険な機能である。そもそもネットコミュニティーは常に匿名性の問題をはらむものであり、住所氏名で登録しても成りすましによるオレオレ詐欺は防げない。メールや電話でいきなり旧友の女の子から連絡が来ても本人である事を確認するのは容易ではない。例えば、大学時代に好きだった女性と似た人と逢っても本人である事を確認するための質問を用意するのはかなりの労力と策を講じないといけない。もっと古い知人になると質問のネタさえ思いつかず悩むだけである。私の携帯はIS01なので背番号はついておらず、危険なSNSには絶対登録できない安全な携帯である。

俺だってこんなSNSに喧嘩を売るような記事は書きたくないよ。でも、SNSを使って成りすまし登録をしてオレオレ詐欺に利用した不逞の輩がいるから仕方なく書いているんだよ。肝心な事は後になってから伝わりそのときには手遅れだ。

|

より以前の記事一覧