This discussion is archived
11 Replies Latest reply: Apr 25, 2008 9:50 AM by 807591 RSS

BigDecimal: merging integer part with fraction fastly and elegantly

807591 Newbie
Currently Being Moderated
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);          
BigDecimal result = left.add(right);
But this decision is not an elegant one and perhaps there is a faster solution, isn't there?

Thank you in advance

Edited by: tell_me_the_truth on Apr 25, 2008 7:41 PM
  • 1. Re: BigDecimal: merging integer part with fraction fastly and elegantly
    800323 Newbie
    Currently Being Moderated
    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
    807591 Newbie
    Currently Being Moderated
    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
    DrClap Expert
    Currently Being Moderated
    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
    807591 Newbie
    Currently Being Moderated
    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);          
    BigDecimal result = left.add(right);
    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
    807591 Newbie
    Currently Being Moderated
    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
    807591 Newbie
    Currently Being Moderated
    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
    807591 Newbie
    Currently Being Moderated
    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
    DrClap Expert
    Currently Being Moderated
    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
    807591 Newbie
    Currently Being Moderated
    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
    DrClap Expert
    Currently Being Moderated
    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
    807591 Newbie
    Currently Being Moderated
         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);          
                   BigDecimal bd1 = left.add(right);
              }
              System.out.println("using the second approach: " + (System.currentTimeMillis() - start1));
         }
    The output is:

    using first approach (BigDecimal(String)): 797
    using the second approach: 344

    I can't understand how you had got the opposite results.