Monday, July 25, 2016

Square root using BigDecimal

This is an implementation of "square root" using BigDecimal.

The Newton's methond:
https://en.m.wikipedia.org/wiki/Newton%27s_method
https://en.m.wikipedia.org/wiki/Integer_square_root
This can be used to find integer square roots.

Test this code here: https://www.jdoodle.com/online-java-compiler/
Delete all of the code on the online compiler website and just copy and paste this code to the website as it is. Then click the button "compile and execute".

The result
If you want more/less accuracy, just change the number 50 to another number.
If you pass 100 as argument, the significant figures will be 100 digits.

If you write like this:

BigDecimal sqrttest1000 = sqrt(new BigDecimal("2"), 1000); //Square root of 2 (1000 digits)
System.out.println(sqrttest1000);


The result is:
...and continues until 1000th digit

The code:

import java.math.BigDecimal;
import java.math.MathContext;

public class HelloWorld
{
   public static void main(String[] args)
   {
        BigDecimal sqrttest1 = sqrt(new BigDecimal("4"), 50); //Square root of 4 (50 significant digits)
        System.out.println(sqrttest1);
        BigDecimal sqrttest2 = sqrt(new BigDecimal("2"), 50); //Square root of 2 (50 significant digits)
        System.out.println(sqrttest2);
        BigDecimal sqrttest3 = sqrt(new BigDecimal("1"), 50); //Square root of 1 (50 significant digits)
        System.out.println(sqrttest3);
    }

    public static BigDecimal sqrt(BigDecimal a, int scale){

        BigDecimal x = new BigDecimal(Math.sqrt(a.doubleValue()), MathContext.DECIMAL64);
        if(scale < 17){
             x = x.setScale(scale, BigDecimal.ROUND_HALF_EVEN);
             return x;
        }

        BigDecimal b2 = new BigDecimal(2);
        for(int tempScale = 16; tempScale < scale; tempScale *= 2){
            x = x.subtract(
                    x.multiply(x).subtract(a).divide(
                    x.multiply(b2), scale, BigDecimal.ROUND_HALF_EVEN));
        }
        return x;
    }
}