This week's book giveaway is in the OCPJP forum.
We're giving away four copies of OCA/OCP Java SE 7 Programmer I & II Study Guide and have Kathy Sierra & Bert Bates on-line!
See this thread for details.
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


Win a copy of OCA/OCP Java SE 7 Programmer I & II Study Guide this week in the OCPJP forum!
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
Author

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?

cheers
Darryl
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

1.3707957192813231133678705725098

And when I run the above program in eclipse I get

1.370795719281323155058771590120159089565277099609375

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.

cheers
Darryl
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.

cheers
Darryl
Jesper de Jong
Java Cowboy
Saloon Keeper

Joined: Aug 16, 2005
Posts: 14279
    
  21

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
 
It is sorta covered in the JavaRanch Style Guide.
 
subject: Loss of precision worry when using Math.pow()