views:

213

answers:

3

I'm writing an app that needs to output Decimals of varying lengths, and varying scale to strings without the decimal point for writing to a flat file as input to another system. e.g.

 12345  -> Length:10, Scale:2              -> 0001234500
 123.45 -> Length:10, Scale:2              -> 0000012345
 123.45 -> Length:10, Scale:3              -> 0000123450
-123.45 -> Length:10, Scale:3, signed:true -> -000123450
 123.45 -> Length:10, Scale:3, signed:true -> +000123450

The function I have written to handle this is below and is going to be called hundreds of thousands of times so I want to make sure that there's not a better, more efficient way to do this. I've looked at ways to get DecimalFormat to do more for me but I can't see it handling my need to format with decimal places but without decimal point.

protected String getFormattedDecimal( String value, int len, int scale, Boolean signed ) throws Exception{
    StringBuffer retVal = new StringBuffer();

    //Need a BigDecimal to facilitiate correct formatting
    BigDecimal bd = new BigDecimal( value );

    //set the scale to ensure that the correct number of zeroes 
    //at the end in case of rounding
    bd = bd.setScale( scale );

    //taking it that if its supposed to have negative it'll be part of the num
    if ( ( bd.compareTo( BigDecimal.ZERO ) >= 0 ) && signed ){
     retVal.append( "+" );
    }   

    StringBuffer sbFormat = new StringBuffer();
    for (int i = 0; i < len; i++)
    {
     sbFormat.append('0');
    }

    DecimalFormat df = new DecimalFormat( sbFormat.toString() );

    retVal.append( df.format( bd.unscaledValue() ) );

    return retVal.toString();
}
+4  A: 

If you are getting your input as String to begin with, why do you need to convert it to BigDecimal and back?

Seems like it'd be a lot faster to find the position of decimal point, compare that to length / scale and pad the string accordingly.

ChssPly76
I'll try it... looks to me like it'll be more code to do the splitting, padding and handling of signed values but I'm willing to give it a try.
MadMurf
Looks like a lot more code but is in fact about 4 times faster, thanks Mate.
MadMurf
+2  A: 

I agree with ChssPly76 wrt manual String manipulation.

However, if you are going to go down the BigDecimal/DecimalFormat route, you might want to consider sharing your DecimalFormats instead of creating a new one with every iteration. Note that these classes are not thread-safe, so if you are using multiple threads to do your processing, you will want to use something like ThreadLocal storage to maintain a formatter per Thread.

btw, have you tested this and found the performance not acceptable or are you just looking for the most efficient solution possible? Note what Donald Knuth says on the topic of early optimization.

akf
Yes, running it through profiler its average base time was .00058 so the 600k odd iterations it ran through took 349 seconds. I'll have a look at manipulating the string using the lengths and see how that performs, was thinking that would be worse with splitting out and handling negatives.
MadMurf
+4  A: 
CPerkins
+1 (although that justly deserves +100 for the effort put in)
ChssPly76
Thanks. Of course, it was your suggestion in the first place. :)
CPerkins
MadMurf