File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
The moose likes Java in General and the fly likes Loss of precision worry when using Math.pow() Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Java in General
Bookmark "Loss of precision worry when using Math.pow()" Watch "Loss of precision worry when using Math.pow()" New topic

Loss of precision worry when using Math.pow()

Darryl Nortje
Ranch Hand

Joined: Jun 11, 2002
Posts: 140
Hi guys,

Don't know if this question belongs in the advanced or beginners java section, so am putting in the intermediate section. Hope this is right, but please move if not.

I have a worry when it comes to floating point values loss of precision. Maybe you guys can help to substiate my worry, or provide a solution to it.

I'm writing a financial application that it working with decimal numbers. Therefore i can't use float or double. Use bigdecimal instead. I need to take 'a decimal value' to the power of 'another decimal value'.

There is the function Math.pow(double a, double b) that returns a double.

If I do this for example:

BigDecimal one = new BigDecimal("1.234");
BigDecimal two = new BigDecimal("1.5");

double answer = Math.pow(one.doubleValue(), two.doubleValue());

BigDecimal result = new BigDecimal(answer);

So my question is, will there be a loss of precision for the variable 'answer' when I call the Math.pow method?

Any comments?

Darryl Nortje
Ranch Hand

Joined: Jun 11, 2002
Posts: 140
Just to expand a little....

When I do the above in the windows calculator I get


And when I run the above program in eclipse I get


So there is a descrepancy... Has loss of precision occured, or is windows calculator rounding off.

How would one do this if in fact loss of precision has occured in the Math.pow method call.

Robert Hill
Ranch Hand

Joined: Feb 24, 2006
Posts: 94
Maybe, run it and get the answer and compare it using a calculator that is accurate to as many places as you can find.

That specific example isn't all that complex, so it should be fairly accurate. It is equivilent to square root of 1.234^3. My Ti-85 graphing calculator returns 1.37079571928, which is precise enough for most applications.

Running the program with 1.5 on Linux the result returned is 1.3707957192813232, without using BigDecimal at the end, using it before the pow90 call is pointless. Is this precise? No, since the real result is irrational, you will never have precision. How precise you need, depends on the situation. 4 significant digits might be peachy in one case, and death or massive problems in another.
[ September 13, 2006: Message edited by: Robert Hill ]
Darryl Nortje
Ranch Hand

Joined: Jun 11, 2002
Posts: 140
Hi there,

Thanks for the reply. I'm not quite sure I follow. Albeit that my example might be bad, there probably is instances where even the rounding off wouldn't help. If you look at example below, it is much much simpler, yet even with rounding gives the totally incorrect result.

double x = 1.0;
double y = 0.8;

System.out.println(x - y);

prints out 0.19999999999999996.

So perhaps ignore my example and how close it is to the real answer. There might be some doubles when you call Math.pow() that also give totally incorrect results that not even rounding will help.

So is there some other way (using BigDecimal) that you can do something similar to Math.pow() without loosing precision.

Jesper de Jong
Java Cowboy
Saloon Keeper

Joined: Aug 16, 2005
Posts: 15082

First you say that you are deliberately not using float and double because you don't want to loose precision, but then you show a piece of code that does convert your BigDecimals to doubles and back. So you are using doubles, even though you just said you didn't want to use them. Ofcourse the precision will not be better than what double provides if you do that.

The types float and double store floating point numbers in binary form. Just like you cannot express some numbers exactly in decimal form, such as 1/3 = 0.33333..., there are numbers that you cannot express exactly in binary form.

The number 0.2 in binary form is written as: 0.00110011001100110011... Note the recurring pattern, just like 0.3333... in decimal; the number just can't be represented exactly in binary form.

Try this instead of your code:

Surprise, surprise! It prints 0.200000 instead of 0.19999999999999996. That's because the formatter that printf() uses rounds the number correctly.

The result "0.19999...96" isn't "totally incorrect". It's correct in the context of the IEEE 754 specification for floating point numbers.
[ September 13, 2006: Message edited by: Jesper Young ]

Java Beginners FAQ - JavaRanch SCJP FAQ - The Java Tutorial - Java SE 8 API documentation
I agree. Here's the link:
subject: Loss of precision worry when using Math.pow()
It's not a secret anymore!