File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Java in General and the fly likes Converting BigDecimal to double Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Java in General
Bookmark "Converting BigDecimal to double" Watch "Converting BigDecimal to double" New topic
Author

Converting BigDecimal to double

Elinor Chang
Ranch Hand

Joined: Jul 30, 2003
Posts: 58
Hello,

I am getting random run time exception when converting BigDecimal to double. The exception is the NumberFormatException. Since we are doing lots of scientific calucaltion, our precision is up to 14 position after the decimal point.

The exception is as the followings:

java.lang.NumberFormatException: For input string: "0.0000000000null"

I am sure the input string isn't "0.0000000000null" when I use it to create the BigDecimal object. It seems the object changes itself after hours application run.

Has anybody encountered similar problem? Again, the exception is random and not repeatable. It could happen anywhere.

Thanks
Elinor


The more I learn, the less I know....<br /> <br />SCJP2 <br />SCWCD
Greg Charles
Sheriff

Joined: Oct 01, 2001
Posts: 2848
    
  11

That's very odd. The source code I'm looking at would make that error impossible. There could be a case if you used the BigDecimal(BigInteger, int scale) constructor, where the constructor wouldn't complain, but doubleValue() would fail with a NullPointerException. It's actually calling toString() and then parsing that String into a double.

What exact version of the JDK are you using? Also, BigDecimal is not a final class. Are you sure you aren't working with a subclass?
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
I agree with Greg's comments, plus:

[Elinor]: I am sure the input string isn't "0.0000000000null" when I use it to create the BigDecimal object. It seems the object changes itself after hours application run.

That seems unlikely as BigDecimal is supposed to be immutable. (You're not using reflection somewhere to change values, are you?) Are you using the doubleValue() conversion method, or something else? (If something else, please show us.)

If you could insert some logging immediately after this instance is created, and also immediately before the attempted conversion, that could be useful. Something like:

Does the string value really say null just before conversion? And if so, can you find an earlier entry where that same instance was created? What was the string value then?


"I'm not back." - Bill Harding, Twister
Jesper de Jong
Java Cowboy
Saloon Keeper

Joined: Aug 16, 2005
Posts: 14103
    
  16

Originally posted by Elinor Chang:
[QB]I am getting random run time exception when converting BigDecimal to double. The exception is the NumberFormatException. Since we are doing lots of scientific calucaltion, our precision is up to 14 position after the decimal point.

Are you converting a BigDecimal to double, or is it the other way around - converting a double to a BigDecimal?

Show us the stack trace and a few lines of source code where the exception happens (the stack trace tells you in which line in which source file the exception happens). That will make it much easier to help you - without the exact error message and some source code we can only guess what's happening in your application.


Java Beginners FAQ - JavaRanch SCJP FAQ - The Java Tutorial - Java SE 7 API documentation
Scala Notes - My blog about Scala
Elinor Chang
Ranch Hand

Joined: Jul 30, 2003
Posts: 58
Here is the stack trace I have so far.

java.lang.NumberFormatException: For input string: "0.0000000000null"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
at java.lang.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1207)
at java.lang.Double.valueOf(Double.java:202)
at java.math.BigDecimal.doubleValue(BigDecimal.java:1033)

It happends when converting BigDecimal to a double not the other way around.

On the other hand, I don't set the BigDecimal which is obtained from Database table. The corresponding column was decleared as decimal(16, 14). I start to suspecting on the data retrival part. I am using Hibernate to get data...

Any idea?
Thanks for all your response so far.
Elinor Chang
Ranch Hand

Joined: Jul 30, 2003
Posts: 58
The JDK I am using is 1.4.2. App Server WebLogic 8.1 Sp3...
Elinor Chang
Ranch Hand

Joined: Jul 30, 2003
Posts: 58
Three more line of error log. I don't use reflection when converting a BigDecimal to double using .doubleValue() but it seems the application does that itself. Any problem on that?

at sun.reflect.GeneratedMethodAccessor305.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
[Elinor]: I don't use reflection when converting a BigDecimal to double using .doubleValue() but it seems the application does that itself. Any problem on that?

No, that's fine. When I mentioned reflection I was talking about using it to directly access fields within the BigDecimal class, bypassing the public methods of the class. You call stack shows it's still giong in through doubleValue(), and anyway it's not changing the value there. There's no problem with the reflection used here.

[Elinor]: I start to suspecting on the data retrival part.

I agree. Most likely this BigDecimal was broken at creation time.

[Elinor]: I am using Hibernate to get data... Any idea?

I would try to confirm this by checking the value of the BigDecimal as soon as possible after it's been loaded. (See my previous comment about logging statements.) If you can confirm the problem is in this area, I'd ask this question in the Object Relational Mapping forum, which covers Hibernate.
Elinor Chang
Ranch Hand

Joined: Jul 30, 2003
Posts: 58
Thanks. I just posted a topic in the forum. Hopefully someone can shine some light on it. On the other hand, I doubt it's hiberate that causes it. Hibernate calls JDBC behind the scene. It might go all the way back to be a glitch on BigDecimal constructor that uses a String.

What do you think about the way of constructing a BigDecimal as the following:

double d = 0.1;
double b = -0.1
double e = d + b;
BigDecimal f = new BigDecimal(""+e);

My further invesitgation narrows the scope down to this line. Since the application does heavy duty scientific calculation, is it possible the ""+e becomes "0.00000000000null"? considering double doesn't keep the precision.

Thanks
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
[Elinor]: What do you think about the way of constructing a BigDecimal as the following:

Seems a little silly - why not just use the new BigDecimal(double) constructor? But it should work.

Since the application does heavy duty scientific calculation, is it possible the ""+e becomes "0.00000000000null"? considering double doesn't keep the precision.

I don't think so, and that doesn't happen when I run that code. Have you tried it on your machine?
Greg Charles
Sheriff

Joined: Oct 01, 2001
Posts: 2848
    
  11

I still can't figure out how it's possible. BigDecimal stores its value internally as a BigInteger and an integer scale. When you call doubleValue(), it first gets a String representation of the BigDecimal, then uses java.lang.Double to parse it. (Even if you used a String to contruct the BigDecimal, that's not what it's using.) If the BigInteger part was null, which is possible through various constructors, then you would fail with a NullPointerException. However, what you are seeing is the toString() method of BigInteger returning null. From what I can see of the BigInteger source, that's simply impossible, no matter how gooped up the internal values are.

I suggest that somehow BigDecimal has been subclassed, or that BigInteger has been subclassed and been used to construct the BigDecimal. You can check the concrete class of your BigDecimal directly. For the internal BigInteger ... well you might be able to look at the class if you can catch it in a debugger. If that's what happening, then I guess it's Hibernate that's doing it. It may be a reported bug somewhere.
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
[Greg]: I still can't figure out how it's possible.

Me neither so far. But there are a lot of internals to sort through here...

However, what you are seeing is the toString() method of BigInteger returning null.

Looks to me like toString() is returning "0.00000000000null". I'm not sure which part internally the null is coming from. Was thinking it might come from BigInteger's toString(int) method screwing up the count of numGroups? Hard to say.

Elinor, it would really be useful to know just what value this BigDecimal had before doubleValue() was invoked. See if you can log the values of f.scale(), f.precision(), and f.unscaledValue() for example. And f.getClass(), and f.unscaledValue().getClass(). Because Greg's suggestion that one of those might be a subclass is more plausible than anything else we've seen so far.
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18541
    
    8

If this error is happening very rarely, then it's possible that unusual numbers are causing it. But I tried with NaN and the "infinities" and got different error messages than that one, so that doesn't look very likely.

However, since you're running this in a Web app container, is it possible that there are violations of thread safety occurring? It might be hard to tell, especially if it's the constructor of BigDecimal that is using some object that isn't thread-safe.
Elinor Chang
Ranch Hand

Joined: Jul 30, 2003
Posts: 58
Thanks everybody's input. Back to some questions you asked.

1. new BigDecimal(""+adouble) vs. new BigDecimal(adouble)

It's not silly to use the first constuctore because it ensure the BigDecimal has the exact number adouble represents. It's actually the best way to create a BigDecimal.

2. Using thread safe object.

We are using HashMap in session bean. Since EJB can garantee thread safe and we don't have the case when two thread modify the HashMap instance at the same time, I don't think the multi-threading is the culprit.

I will try to catch the run time exception and do something....

On the other hand, if anybody has experience in ILOG JRule Engine please let me know if the ILOG exeuction model does something funny when dealing with BigDecimal...

Thanks!
Tony Morris
Ranch Hand

Joined: Sep 24, 2003
Posts: 1608
<two-cents>
I don't know if anyone has mentioned it yet, but my best guess is that you have a race condition that is consistently occurring. It only takes a few seconds to figure out what is happening under a debugger though quite often, a race condition exhibits different behaviour under a debugger. In all cases, it's a 30 second diagnosis.
</two-cents>


Tony Morris
Java Q&A (FAQ, Trivia)
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Converting BigDecimal to double