@@ -32,26 +32,38 @@ private static BigDecimal approximatePi() {
3232
3333 /**
3434 * 使用泰勒级数展开计算arctan(x)
35- * @param x x
36- * @param mc 精度
35+ * @param x 输入值,|x| ≤ 1时效果最好
36+ * @param mc 精度上下文
3737 * @return arctan(x)
3838 */
3939 public static BigDecimal arctan (BigDecimal x , MathContext mc ) {
40+ if (x .compareTo (BigDecimal .ZERO ) == 0 )
41+ return BigDecimal .ZERO ;
42+ boolean needAdjust = x .abs ().compareTo (BigDecimal .ONE ) > 0 ;
43+ BigDecimal workingX = needAdjust ? BigDecimal .ONE .divide (x , mc ) : x ;
4044 BigDecimal result = BigDecimal .ZERO ;
41- BigDecimal xSquared = x .multiply (x );
42- BigDecimal term = x ;
43- boolean add = true ;
45+ BigDecimal xSquared = workingX .multiply (workingX , mc );
46+ BigDecimal term = workingX ;
4447 BigDecimal tolerance = BigDecimal .ONE .scaleByPowerOfTen (-mc .getPrecision ());
45- for (int i = 1 ; term .abs ().compareTo (tolerance ) > 0 ; i += 2 ) {
46- if (add )
47- result = result .add (term );
48- else
49- result = result .subtract (term );
50- term = term .multiply (xSquared ).divide (
51- BigDecimal .valueOf (i + 2 ), mc );
48+ int n = 0 ;
49+ boolean add = true ;
50+ while (term .abs ().compareTo (tolerance ) >= 0 ) {
51+ result = add ? result .add (term , mc ): result .subtract (term , mc );
52+ n ++;
53+ term = term .multiply (xSquared , mc )
54+ .multiply (BigDecimal .valueOf (2L * n - 1 ), mc )
55+ .divide (BigDecimal .valueOf (2L * n + 1 ), mc );
5256 add = !add ;
57+ if (n > mc .getPrecision () * 10 )
58+ break ;
5359 }
54- return result ;
60+ if (needAdjust ) {
61+ BigDecimal piOver2 = BigDecimal .valueOf (Math .PI ).round (mc ).divide (BigDecimal .valueOf (2 ), mc );
62+ result = piOver2 .subtract (result , mc );
63+ if (x .compareTo (BigDecimal .ZERO ) < 0 )
64+ result = result .negate ();
65+ }
66+ return result .round (mc );
5567 }
5668
5769 /**
0 commit comments