11 Replies Latest reply: Apr 25, 2008 11:50 AM by 807591

# BigDecimal: merging integer part with fraction fastly and elegantly

Hi all, I have two long values: long1 and long2 and I need to create a BigDecimal with value long1.long2 . Creating String object of these long values and using constructor BigDecimal(String) like
``````long long1 = 15;
long long2 = 82;
BigDecimal res = new BigDecimal(String.valueOf(long1)+"."+String.valueOf(long2));``````
is too slow.
Of course I can achieve the goal writing something like that:
``````          long long1 = 15;
long long2 = 82;
BigDecimal right = new BigDecimal(long1);
BigDecimal left = new BigDecimal(long2);
int delta = 0;
// count amount of digits
while (true) {
if (long1 == 0)
break;
long1 = long1 / 10;
delta++;
}
right = right.movePointLeft(delta);
But this decision is not an elegant one and perhaps there is a faster solution, isn't there?

Edited by: tell_me_the_truth on Apr 25, 2008 7:41 PM
• ###### 1. Re: BigDecimal: merging integer part with fraction fastly and elegantly
Actually, using the String constructor of BigDecimal is the recommend way to create on (so that you do not have the IEEE floating point "problem").
What makes you say it is too slow?
• ###### 2. Re: BigDecimal: merging integer part with fraction fastly and elegantly
What makes you think that the first attempt was too slow? How many times
are you performing that operation? Have you tested and proven that that's a bottleneck?
Donald Knuth:
"We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil."
• ###### 3. Re: BigDecimal: merging integer part with fraction fastly and elegantly
Sorry, once you decide the elegant solution is too slow (you do have empirical justification for that, right?) then in getting faster solutions you can't still demand elegance.

I'm curious about a requirement that can never generate something like 15.035; is your data really structured like that?
• ###### 4. Re: BigDecimal: merging integer part with fraction fastly and elegantly
tell_me_the_truth wrote:
Hi all, I have two long values: long1 and long2 and I need to create a BigDecimal with value long1.long2 . Creating String object of these long values and using constructor BigDecimal(String) like
``````long long1 = 15;
long long2 = 82;
BigDecimal res = new BigDecimal(String.valueOf(long1)+"."+String.valueOf(long2));``````
is too slow.
Can you explain how you came to that conclusion?
Of course I can achieve the goal writing something like that:
``````          long long1 = 15;
long long2 = 82;
BigDecimal right = new BigDecimal(long1);
BigDecimal left = new BigDecimal(long2);
int delta = 0;
// count amount of digits
while (true) {
if (long1 == 0)
break;
long1 = long1 / 10;
delta++;
}
right = right.movePointLeft(delta);
And how you figure this will be any faster than the String concatenation version?
But this decision is not an elegant one and perhaps there is a faster solution, isn't there?
Unless you have a valid reason to need to improve the speed of this operation (as in, you've profiled the app and this code is a bottleneck), then don't worry about speed, worry about readability and maintainability of your code.
• ###### 5. Re: BigDecimal: merging integer part with fraction fastly and elegantly
Thank you for your answers. I have tested the speed in nano seconds of the first solution(using constructor with String) an of the second one. the second solution was rather faster. Time is critical in my project - that's why I'm seeking for a better solution.
• ###### 6. Re: BigDecimal: merging integer part with fraction fastly and elegantly
Code-level optimization is not effective before you've determined what the bottlenecks are. Profile the entire application and determine where you should be spending your optimization time. Trying to microoptimize every line of code will result in a project that is impossible to read or maintain. I'd also highly doubt you'd be able to deliver on time (or ever).
• ###### 7. Re: BigDecimal: merging integer part with fraction fastly and elegantly
The problem is that this assignment(creating BigDecimal object of two longs) is performed a huge(really huge) amount of times and I must implement something which really "flyes". That's why I am investigating this point.
• ###### 8. Re: BigDecimal: merging integer part with fraction fastly and elegantly
Nanoseconds?

I ran each of your two proposed versions in a loop one million times and timed the loops. The first (elegant) version took 1687 milliseconds and the second (allegedly fast) version took 2547 milliseconds.

Not looking good for micro-optimization yet. But wait... my code doesn't do anything with the BigDecimal objects, so maybe the runtime optimized those statements away. Could make a difference. So let's assign them to something which I print at the end: now elegant=1625 and fast=2500.

So, did anybody quote my brother Knuth about premature optimization yet? Oh yeah, there it is. Seconded.
• ###### 9. Re: BigDecimal: merging integer part with fraction fastly and elegantly
It's hard to believe. I have tested it and got quite the opposite results. Could you show your testing application? Thanks
• ###### 10. Re: BigDecimal: merging integer part with fraction fastly and elegantly
Here's part of it:
``````int loops = 1000000;
BigDecimal bd = null;
long start = System.currentTimeMillis();
for (int i=0; i<loops; i++) {
long long1 = 15;
long long2 = 82;
bd = new BigDecimal(String.valueOf(long1)+"."+String.valueOf(long2));
}
System.out.println(System.currentTimeMillis() - start);``````
It should be obvious to you what the second part is.
• ###### 11. Re: BigDecimal: merging integer part with fraction fastly and elegantly
``````     public static void main(String[] args) {
int loops = 1000000;
BigDecimal bd = null;
long start = System.currentTimeMillis();
for (int i = 0; i < loops; i++) {
long long1 = 15;
long long2 = 82;
bd = new BigDecimal(String.valueOf(long1) + "."
+ String.valueOf(long2));
}
System.out.println("using first approach (BigDecimal(String)): " + (System.currentTimeMillis() - start));

long start1 = System.currentTimeMillis();
for (int i = 0; i < loops; i++) {
long long1 = 15;
long long2 = 82;
BigDecimal right = new BigDecimal(long1);
BigDecimal left = new BigDecimal(long2);
int delta = 0;
while (true) {
if (long1 == 0)
break;
long1 = long1 / 10;
delta++;
}
right = right.movePointLeft(delta);