为了账号安全,请及时绑定邮箱和手机立即绑定

Java中BigDecimal的平方根

/ 猿问

Java中BigDecimal的平方根

慕雪6173905 2019-10-18 15:01:28

我们可以BigDecimal仅使用Java API而不使用定制的100行算法来计算Java 中a的平方根吗?



查看完整描述

3 回答

?
繁星coding

我已经用过了,效果很好。 这是该算法在更高层次上如何工作的示例。


编辑:我很好奇,看看这是多么准确如下定义。这是来自官方来源的sqrt(2):


(first 200 digits) 1.41421356237309504880168872420969807856967187537694807317667973799073247846210703885038753432764157273501384623091229702492483605585073721264412149709993583141322266592750559275579995050115278206057147

这里使用的是我在下面概述的SQRT_DIG等于150的方法:


(first 200 digits) 1.41421356237309504880168872420969807856967187537694807317667973799073247846210703885038753432764157273501384623091229702492483605585073721264412149709993583141322266592750559275579995050115278206086685

第一个偏差出现在195位精度之后。如果您需要如此高的精度,则需要您自担风险。


更改SQRT_DIG为1000可获得1570位精度。


private static final BigDecimal SQRT_DIG = new BigDecimal(150);

private static final BigDecimal SQRT_PRE = new BigDecimal(10).pow(SQRT_DIG.intValue());


/**

 * Private utility method used to compute the square root of a BigDecimal.

 * 

 * @author Luciano Culacciatti 

 * @url http://www.codeproject.com/Tips/257031/Implementing-SqrtRoot-in-BigDecimal

 */

private static BigDecimal sqrtNewtonRaphson  (BigDecimal c, BigDecimal xn, BigDecimal precision){

    BigDecimal fx = xn.pow(2).add(c.negate());

    BigDecimal fpx = xn.multiply(new BigDecimal(2));

    BigDecimal xn1 = fx.divide(fpx,2*SQRT_DIG.intValue(),RoundingMode.HALF_DOWN);

    xn1 = xn.add(xn1.negate());

    BigDecimal currentSquare = xn1.pow(2);

    BigDecimal currentPrecision = currentSquare.subtract(c);

    currentPrecision = currentPrecision.abs();

    if (currentPrecision.compareTo(precision) <= -1){

        return xn1;

    }

    return sqrtNewtonRaphson(c, xn1, precision);

}


/**

 * Uses Newton Raphson to compute the square root of a BigDecimal.

 * 

 * @author Luciano Culacciatti 

 * @url http://www.codeproject.com/Tips/257031/Implementing-SqrtRoot-in-BigDecimal

 */

public static BigDecimal bigSqrt(BigDecimal c){

    return sqrtNewtonRaphson(c,new BigDecimal(1),new BigDecimal(1).divide(SQRT_PRE));

}

请务必查看barwnikk的答案。它更简洁,看起来精度更高或更高。


查看完整回答
反对 回复 2019-10-18
?
暮色呼如

public static BigDecimal sqrt(BigDecimal A, final int SCALE) {

    BigDecimal x0 = new BigDecimal("0");

    BigDecimal x1 = new BigDecimal(Math.sqrt(A.doubleValue()));

    while (!x0.equals(x1)) {

        x0 = x1;

        x1 = A.divide(x0, SCALE, ROUND_HALF_UP);

        x1 = x1.add(x0);

        x1 = x1.divide(TWO, SCALE, ROUND_HALF_UP);


    }

    return x1;

}

这项工作完美!超过65536位的数字非常快!


查看完整回答
反对 回复 2019-10-18
?
不负相思意

通过使用Karp的技巧,可以仅在两行中实现无循环,从而提供32位精度:


public static BigDecimal sqrt(BigDecimal value) {

    BigDecimal x = new BigDecimal(Math.sqrt(value.doubleValue()));

    return x.add(new BigDecimal(value.subtract(x.multiply(x)).doubleValue() / (x.doubleValue() * 2.0)));

}


查看完整回答
反对 回复 2019-10-18

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信