版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/sdau20163942/article/details/82933784
有时在用JAVA大数BigInteger时会面临一个问题:BigInteger没有sqrt函数。这里可以用牛顿法来求一个精度较高的sqrt(C),操作用JAVA的BigDecimal来实现。
牛顿法如下(见《数值分析》课本):
- 对于给定的正数C,应用牛顿法解二次方程。X^2-C=0;
- 可导出求开方值sqrt(C)的计算程序:x_k+1=1/2*(x_k+C/x_k);
例如求sqrt(115):
- 取初值x_0=10,对C=115按上式跌倒三次便可得到精度为1e-6的结果。
- 由于上面公式对于任意初始值x_0均收敛,并且收敛的速度很快,因此我们可取确定的初值如x_0=1编制通用程序。用这个通用程序求sqrt(115),也只要迭代7次便得到了上面的结果10.723805.
写好的JAVA函数如下:
static BigDecimal NewtonSqrt(double inC)//求高精度sqrt(inC)
{
BigDecimal pre=BigDecimal.valueOf(1);//初始值
BigDecimal now=null;
BigDecimal C=BigDecimal.valueOf(inC);
BigDecimal half=BigDecimal.valueOf(0.5);
for(int i=1;i<=100;i++) //迭代100次
{
now=half.multiply(pre.add(C.divide(pre,120,BigDecimal.ROUND_HALF_DOWN)));//保留小数点后120
pre=now;
}
return now;
}
附:JAVA中BigDecimal的一些操作如下:
初始化:
- BigDecimal的两种常用构造方法:
- ①.BigDecimal b = new BigDecimal("2.3");
- ②.BigDecimal b = BigDecimal.valueOf(2.3);
- 用方法一时不建议用double类型作为实参,因为会产生较大误差(由于二进制缘故)。
- 要开根号的本来就是double类型时最好用方法②,或可将double用Double.toString(double)转化为String再用方法①
BigDecimal的除法BigDecimal.divide():
- 其实divide方法有可以传三个参数:public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode)
- 第一参数表示除数, 第二个参数表示小数点后保留位数,
- 第三个参数表示舍入模式,只有在作除法运算或四舍五入时才用到舍入模式,有下面这几种:
ROUND_CEILING //向正无穷方向舍入
ROUND_DOWN //向零方向舍入
ROUND_FLOOR //向负无穷方向舍入
ROUND_HALF_DOWN //向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,向下舍入, 例如1.55 保留一位小数结果为1.5
ROUND_HALF_EVEN //向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,如果保留位数是奇数,使用ROUND_HALF_UP,如果是偶数,使用ROUND_HALF_DOWN
ROUND_HALF_UP //向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,向上舍入, 1.55保留一位小数结果为1.6
ROUND_UNNECESSARY //计算结果是精确的,不需要舍入模式
ROUND_UP //向远离0的方向舍入