ところで、前回のGauss-Legendre法でBigDecimal版sqrtを使いました。で、この中の処理である程度の精度までをdoubleで求めてるのですが、これの効果がどれだけあるか確認しました。
まず、doubleを使ったsqrtで100桁までの円周率を100回求めると、処理時間は0.54秒でした。
これをdoubleを使わず次のようなsqrtを使うと、3.22秒になりました。6倍くらい違います。
public static BigDecimal sqrt(BigDecimal a, int scale){ BigDecimal b2 = new BigDecimal(2); BigDecimal x = a; for(int tempScale = 1; tempScale < scale * 2; tempScale *= 2){ //x = x - (x * x - a) / (2 * x); x = x.subtract( x.multiply(x).subtract(a).divide( x.multiply(b2), Math.min(scale, tempScale * 2), BigDecimal.ROUND_HALF_EVEN)); } return x; }
というわけで、doubleを使って途中までの値を求めておくことには効果があることがわかりました。というか、想像以上に差があったんですが、なんでだろう?
ついでに、マチンの公式による方法で円周率100桁を100回求めると2.87秒でした。Gauss-Legendre法より速い。
これについては、桁数を増やすと挽回するんではないかと思います。