# Thread: square rooting a BigDecimal

1. ## square rooting a BigDecimal

Anyone know how I can take the square root of a bigDecimal with keeping the precision. I found the BigDecimal method pow(), so I could take the power to the .5. But this method only accepts ints.

2. Java Code:
```package bigroot;
import java.math.BigDecimal;
import java.math.BigInteger;
//sqrt-function copied of BigFunctionsClass
//From The Java Programmers Guide To numerical Computing (Ronald Mak, 2003)
public class BigRoot {
/**
* Compute the square root of x to a given scale, x >= 0.
* Use Newton's algorithm.
* @param x the value of x
* @param scale the desired scale of the result
* @return the result value
*/
public static BigDecimal sqrt(BigDecimal x, int scale)
{
// Check that x >= 0.
if (x.signum() < 0) {
throw new IllegalArgumentException("x < 0");
}

// n = x*(10^(2*scale))
BigInteger n = x.movePointRight(scale << 1).toBigInteger();

// The first approximation is the upper half of n.
int bits = (n.bitLength() + 1) >> 1;
BigInteger ix = n.shiftRight(bits);
BigInteger ixPrev;

// Loop until the approximations converge
// (two successive approximations are equal after rounding).
do {
ixPrev = ix;

// x = (x + n/x)/2

} while (ix.compareTo(ixPrev) != 0);

return new BigDecimal(ix, scale);
}
}```
Java Code:
```package bigroot;
import java.math.BigDecimal;
/**
* Test the BigFunctions by comparing results with class java.lang.Math.
*/
public class TestBigRoot
{
private static final int SCALE = 40;
private void run()
{
System.out.println("sqrt 2 = " + Math.sqrt(2));
System.out.println("       = " + BigRoot.sqrt(BigDecimal.valueOf(2), SCALE));
System.out.println("sqrt 26 = " + Math.sqrt(26));
System.out.println("       = " + BigRoot.sqrt(BigDecimal.valueOf(26), SCALE));
}

public static void main(String args[])
{
TestBigRoot test = new TestBigRoot();

try {
test.run();
}
catch(Exception ex) {
System.out.println("ERROR: " + ex.getMessage());
}
}
}```
Don't ask me to explain the code, I just copied it and hope not to get sued. Also in the 26-test there seems to be a rounding error, but I don't know if Math or this algorithm is to blame.

3. Originally Posted by ryanmk54
Anyone know how I can take the square root of a bigDecimal with keeping the precision. I found the BigDecimal method pow(), so I could take the power to the .5. But this method only accepts ints.
A fast iteration method is: sq(n) = (n/sq(n-1)+sq(n-1))/2 and a reasonable estimation for sq(0) = n/2.

kind regards,

Jos

4. Thanks. I am not going to try to understand it now, but it does a great job of what I want it to.

5. Originally Posted by ryanmk54
Thanks. I am not going to try to understand it now, but it does a great job of what I want it to.
My reply #3 (accidentally) described how the method in reply #2 works: take the average of the current estimation and the result of the estimation. The fixed point of the recurrence relation has to be sqrt(n). It converges quadratically.

kind regards,

Jos

6. Originally Posted by ryanmk54
Anyone know how I can take the square root of a bigDecimal with keeping the precision. I found the BigDecimal method pow(), so I could take the power to the .5. But this method only accepts ints.
I'm curious what application requires this degree of precision for what is essentially a floating point operation.

7. Originally Posted by Fubarable
I'm curious what application requires this degree of precision for what is essentially a floating point operation.
Me too; a bit of algebra normally cancels out those square roots ...

kind regards,

Jos

8. My reply #3 (accidentally) described how the method in reply #2 works.
Thanks. I admit I didn't notice it.

9. Originally Posted by Jodokus
Thanks. I admit I didn't notice it.
Nevermind; almost nobody does ;-) my replies are too small or too technical or not enough spoonfeeding; they seem mostly invisible ;-)

kind regards,

Jos (who?)

10. Originally Posted by Fubarable
I'm curious what application requires this degree of precision for what is essentially a floating point operation.
I am just making a basic calculator. I read a forum post a while back that said if you are adding money or anything like that you should never use double. You should use BigDecimal.

Were you suggesting I convert the BigDecimal to an int or just use double? I haven't made very much java yet. I just do it in my spare time.

11. Originally Posted by ryanmk54
I am just making a basic calculator. I read a forum post a while back that said if you are adding money or anything like that you should never use double. You should use BigDecimal.

Were you suggesting I convert the BigDecimal to an int or just use double? I haven't made very much java yet. I just do it in my spare time.
Are you making a general purpose (basic) calculator, or are you building a financial calculator? If it's the former, ordinary doubles would do fine (unless you want unlimited precision). If it is a financial calculator it depends on the type of calculations you want to perform. So, it's your turn to elaborate on this ;-)

kind regards,

Jos

12. Originally Posted by JosAH
Are you making a general purpose (basic) calculator, or are you building a financial calculator? If it's the former, ordinary doubles would do fine (unless you want unlimited precision). If it is a financial calculator it depends on the type of calculations you want to perform. So, it's your turn to elaborate on this ;-)

kind regards,

Jos

Its just a general purpose calculator. I think I'll stick with BigDecimal because I like the automatic scaling ability

13. Just a warning: you'll need a book then like mentioned in the listing, and Jos/Fubarable are right, working with doubles is almost allways more then needed (and a good, (not-Polish-notation-) calculator is difficult enough). But it would be a challenge. Tell here when you're done!

14. Originally Posted by Jodokus
Just a warning: you'll need a book then like mentioned in the listing, and Jos/Fubarable are right, working with doubles is almost allways more then needed (and a good, (not-Polish-notation-) calculator is difficult enough). But it would be a challenge. Tell here when you're done!
Is polish notation where you can enter like five operations at once (5+6*5-9+1). My calculator is extremely basic. Two numbers an operator and answer. It works right now but I'm still planning on adding some features(menu bar , log window, .
rounding preferences, etc)

15. Moderator
Join Date
Feb 2009
Location
New Zealand
Posts
4,565
Rep Power
12
No in polish notation your example would be entered as 5,6,5,*,+,9,1,+,- (I think!)

The nice thing is that the order of operations is unambiguously specified without parentheses. The downside is that only Poles can understand it.

The notation is described at Polish notation - Wikipedia, the free encyclopedia - the example I gave seems to be Reverse Polish notation - Wikipedia, the free encyclopedia.

16. Originally Posted by pbrockway2
No in polish notation your example would be entered as 5,6,5,*,+,9,1,+,- (I think!)

The nice thing is that the order of operations is unambiguously specified without parentheses. The downside is that only Poles can understand it.

The notation is described at Polish notation - Wikipedia, the free encyclopedia - the example I gave seems to be Reverse Polish notation - Wikipedia, the free encyclopedia.
Yep, also, if the arity of the operators/functions is known and fixed you don't need those irritating parentheses in Polish notation either, e.g. 3*(4+5) is * 3 + 4 5 in Polish notation and is unambiguous, as is the reverse Polish notation 3 4 5 + * It's the variadic functions/operators that mess things up, e.g. (+ 1 2 3) where the + operator takes three arguments. There also is the functional notation (sometimes called 'outer Lisp') where the operators are used as functions, so 3*(4+5) is written as *(3, +(4, 5)). If the comma isn't a function/operator itself it can be left out.

kind regards,

Jos

17. I just can't leave for a moment! The explanations of Jos and PBrockway are perfect, and google also knows something about it. I just mentioned it because it is supposedly easier to program: you don't need the parsing. But indeed, only Polish people seem to understand or like it.
(In effect what you do on a small calculator with just an in-between result showing is a bit like reverse Polish notation (but cheating by using a memory): just enter arguments followed by an operator all the time.)
Last edited by Jodokus; 05-22-2011 at 02:23 PM. Reason: forgot "reverse"

18. Originally Posted by Jodokus
I just can't leave for a moment! The explanations of Jos and PBrockway are perfect, and google also knows something about it. I just mentioned it because it is supposedly easier to program: you don't need the parsing. But indeed, only Polish people seem to understand or like it.
(In effect what you do on a small calculator with just an in-between result showing is a bit like Polish notation (but cheating by using a memory): just enter arguments followed by an operator all the time.)
That's not entirely true, all three forms need a bit of parsing, e.g. + * - doesn't make sense for a postfix expression (reverse Polish) if there are no operands available on the data stack; equivalently * 3 - doesn't make sense as an infix expression, nor does it as a prefix expression (Polish notation). On the other hand those parsers are minimal compared to the lexical analyzers needed in all three of the expression forms.

kind regards,

Jos