Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8165814

Sqrt of a BigDecimal

XMLWordPrintable

    • generic
    • generic

      A DESCRIPTION OF THE REQUEST :
      I have often needed the square root of a positive BigDecimal, and each time I have rolled my own. Today, I came across a really nice algorithm, and a new algorithm I had not seen before. Both are from the Wikipedia article "Newton-Raphson Method." I hope you can include something like them in BigDecimal. We also need a Log to base b routine in BigDecimal, for which I don't have a good solution yet. The Halley''s routine exhibits cubic convergence, while Newton-Raphson is only quadratic. The text case shows no difference between the two, but the difference exists as seen in other problems.

      JUSTIFICATION :
      Square root arises all them time and in many algorithms.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The ability to take the square root of a positive BigDecimal.
      ACTUAL -
      User must write his or her own.

      ---------- BEGIN SOURCE ----------
      /*
       * To change this license header, choose License Headers in Project Properties.
       * To change this template file, choose Tools | Templates
       * and open the template in the editor.
       */
      package testbdsqrt;

      import java.math.BigDecimal;
      import static java.math.BigDecimal.ONE;
      import static java.math.BigDecimal.ZERO;
      import java.math.MathContext;
      import java.util.ArrayList;

      /**
       *
       * @author CElliott
       */
      public class TestBDSqrt {
        private static final BigDecimal TWO = ONE.add(ONE);
        private static final BigDecimal THREE = TWO.add(ONE);
        private static final MathContext mc = new MathContext(66);
        

        
        public static BigDecimal NewtonRaphsonSqrt( BigDecimal n, double tolerance, MathContext mc ) throws IllegalArgumentException{
          if( n.compareTo(ZERO) < 0 )
            throw new IllegalArgumentException("Aruments to NewtonRaphsonSqrt must be positive.");
          ArrayList<BigDecimal> results = new ArrayList<>();
          BigDecimal xnp1 = new BigDecimal(Math.sqrt(n.doubleValue()), mc);
          results.add(xnp1);
          xnp1 = xnp1.add(n.divide(xnp1, mc)).divide(TWO, mc);
          //System.out.printf("%30.25f%n", xnp1);
          while(true){
            if(xnp1.subtract(results.get(results.size()-1), mc).abs(mc).doubleValue()<=tolerance)
              break;
            results.add(xnp1);
            xnp1 = xnp1.add(n.divide(xnp1, mc)).divide(TWO, mc);
            //System.out.printf("%30.25f%n", xnp1);
          }
          results.add(xnp1);
          return results.get(results.size()-1);
        }
        
        public static BigDecimal HalleysSqrt( BigDecimal n, double tolerance, MathContext mc ) throws IllegalArgumentException{
          if( n.compareTo(ZERO) < 0 )
            throw new IllegalArgumentException("Aruments to HalleysSqrt must be positive.");
          ArrayList<BigDecimal> results = new ArrayList<>();
          BigDecimal xnp1 = new BigDecimal(Math.sqrt(n.doubleValue()), mc);
          results.add(xnp1);
          xnp1 = THREE.multiply(n, mc).add(xnp1.pow(2,mc), mc).divide(n.divide(xnp1, mc).add(THREE.multiply(xnp1, mc)), mc);
          //System.out.printf("%30.25f%n", xnp1);
          while(true){
            if(xnp1.subtract(results.get(results.size()-1), mc).abs(mc).doubleValue()<=tolerance)
              break;
            results.add(xnp1);
            xnp1 = THREE.multiply(n, mc).add(xnp1.pow(2,mc), mc).divide(n.divide(xnp1,mc).add(THREE.multiply(xnp1, mc)), mc);
            //System.out.printf("%30.25f%n", xnp1);
          }
          results.add(xnp1);
          return results.get(results.size()-1);
        }
        /**
         * @param args the command line arguments
         */
        public static void main(String[] args) {
          BigDecimal arg = new BigDecimal(Long.MAX_VALUE);
          arg = arg.pow(2).add(new BigDecimal("0.12345678987654321"));
          BigDecimal results = NewtonRaphsonSqrt(arg, 0.0000000000000001, mc);
          System.out.println();
          System.out.printf("The Newton-Raphson Sqrt of %f is %30.25f, whose square is %30.25f%n", arg, results, results.pow(2));
        
          results = HalleysSqrt(arg, 0.0000000000000001, mc);
          System.out.println();
          System.out.printf("The Halley's Sqrt of %f is %30.25f, whose square is %30.25f%n", arg, results, results.pow(2));
       }
      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      /*
       * To change this license header, choose License Headers in Project Properties.
       * To change this template file, choose Tools | Templates
       * and open the template in the editor.
       */
      package testbdsqrt;

      import java.math.BigDecimal;
      import static java.math.BigDecimal.ONE;
      import static java.math.BigDecimal.ZERO;
      import java.math.MathContext;
      import java.util.ArrayList;

      /**
       *
       * @author CElliott
       */
      public class TestBDSqrt {
        private static final BigDecimal TWO = ONE.add(ONE);
        private static final BigDecimal THREE = TWO.add(ONE);
        private static final MathContext mc = new MathContext(66);
        

        
        public static BigDecimal NewtonRaphsonSqrt( BigDecimal n, double tolerance, MathContext mc ) throws IllegalArgumentException{
          if( n.compareTo(ZERO) < 0 )
            throw new IllegalArgumentException("Aruments to NewtonRaphsonSqrt must be positive.");
          ArrayList<BigDecimal> results = new ArrayList<>();
          BigDecimal xnp1 = new BigDecimal(Math.sqrt(n.doubleValue()), mc);
          results.add(xnp1);
          xnp1 = xnp1.add(n.divide(xnp1, mc)).divide(TWO, mc);
          //System.out.printf("%30.25f%n", xnp1);
          while(true){
            if(xnp1.subtract(results.get(results.size()-1), mc).abs(mc).doubleValue()<=tolerance)
              break;
            results.add(xnp1);
            xnp1 = xnp1.add(n.divide(xnp1, mc)).divide(TWO, mc);
            //System.out.printf("%30.25f%n", xnp1);
          }
          results.add(xnp1);
          return results.get(results.size()-1);
        }
        
        public static BigDecimal HalleysSqrt( BigDecimal n, double tolerance, MathContext mc ) throws IllegalArgumentException{
          if( n.compareTo(ZERO) < 0 )
            throw new IllegalArgumentException("Aruments to HalleysSqrt must be positive.");
          ArrayList<BigDecimal> results = new ArrayList<>();
          BigDecimal xnp1 = new BigDecimal(Math.sqrt(n.doubleValue()), mc);
          results.add(xnp1);
          xnp1 = THREE.multiply(n, mc).add(xnp1.pow(2,mc), mc).divide(n.divide(xnp1, mc).add(THREE.multiply(xnp1, mc)), mc);
          //System.out.printf("%30.25f%n", xnp1);
          while(true){
            if(xnp1.subtract(results.get(results.size()-1), mc).abs(mc).doubleValue()<=tolerance)
              break;
            results.add(xnp1);
            xnp1 = THREE.multiply(n, mc).add(xnp1.pow(2,mc), mc).divide(n.divide(xnp1,mc).add(THREE.multiply(xnp1, mc)), mc);
            //System.out.printf("%30.25f%n", xnp1);
          }
          results.add(xnp1);
          return results.get(results.size()-1);
        }
        /**
         * @param args the command line arguments
         */
        public static void main(String[] args) {
          BigDecimal arg = new BigDecimal(Long.MAX_VALUE);
          arg = arg.pow(2).add(new BigDecimal("0.12345678987654321"));
          BigDecimal results = NewtonRaphsonSqrt(arg, 0.0000000000000001, mc);
          System.out.println();
          System.out.printf("The Newton-Raphson Sqrt of %f is %30.25f, whose square is %30.25f%n", arg, results, results.pow(2));
        
          results = HalleysSqrt(arg, 0.0000000000000001, mc);
          System.out.println();
          System.out.printf("The Halley's Sqrt of %f is %30.25f, whose square is %30.25f%n", arg, results, results.pow(2));
       }
      }


            darcy Joe Darcy
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: