java - BigDecimal formatting -
i'd format bigdecimal in java 8 characters (including seperator), rounding half-up. examples:
12345.6789 -> "12345.68" 123 -> " 123.0" 0.12345678 -> "0.123457" 1.5 -> " 1.5" 0.0045 -> " 0.0045" 12 -> " 12.0"
the result must have leading spaces fill 8 characters. what's easiest way?
i'm pretty sure not best way, it's 1 way.
first note if numbers have more 6 digits before period, or more more width - 2
digits before period, format .0
not work anymore.
string.format()
uses half rounding method, can use first step output 8 characters.
bigdecimal b = new bigdecimal(0.0045); string format = "%8f"; string str = string.format(format, b);
output:
12345.678900 123.000000 0.123457 1.500000 0.004500 12.000000 123456.000000
by default string.format()
uses precision of 6 bigdecimal
. custom precision, need know how many digits before period , substract number (+ 1 period itself) total width.
width - digits - 1
to number of digits can check if (number % radix) == number
applies radix = 10, 100, 1000, ... fits know number of digits.
public static int digitsbeforeperiod(bigdecimal b) { int number = b.intvalue(); int radix = 10; int digits = 1; while((number % radix) != number) { radix *= 10; ++digits; } return digits; }
so next step modify format:
bigdecimal b = new bigdecimal(0.0045); int digits = digitsbeforeperiod(b); string format = "%8." + (8 - digits - 1) + "f"; string str = string.format(format, b);
output:
12345.68 123.0000 0.123457 1.500000 0.004500 12.00000 123456.0
still there lots of 0s, @ least rounding correct now. specify if number round integer, want print .0
suffix, otherwise without.
to achieve there might exist clever formats, didn't think further though. naive way simply:
while(str.endswith("0") && !str.endswith(".0")) { str = str.substring(0, str.length()-1); }
this removes last character of string until either doesn't end on 0
@ or ends .0
.
now numbers have correct format, not aligned correctly:
12345.68 123.0 0.123457 1.5 0.0045 12.0 123456.0
to align them, use string.format()
again.
str = string.format("%" + width + "s", str);
output:
12345.68 123.0 0.123457 1.5 0.0045 12.0 123456.0
in context looks following. note included check wether or not number can formatted way - if not, print invalid. can of course print number, wanted show limitations of format.
public static string trimtowidth(bigdecimal b, int width) { string str = "invalid"; int digits = digitsbeforeperiod(b); // -2 period , 0 if(digits <= width - 2) { // use width , (width - digits - 1) precision (-1 period) string format = "%" + width + "." + (width - digits - 1) + "f"; // rounds half-up str = string.format(format, b); // trim trailing 0s, unless it's .0 while(str.endswith("0") && !str.endswith(".0")) { str = str.substring(0, str.length()-1); } } // add spaces in front str = string.format("%" + width + "s", str); return str; } public static int digitsbeforeperiod(bigdecimal b) { int number = b.intvalue(); int radix = 10; int d = 1; while((number % radix) != number) { radix *= 10; ++d; } return d; } public static void main(string[] args) { double[] values = new double[] { 12345.6789, 123, 0.12345678, 1.5, 0.0045, 12, 123456, 1234567 }; bigdecimal[] bigs = new bigdecimal[values.length]; for(int = 0; < bigs.length; ++i) { bigs[i] = new bigdecimal(values[i]); system.out.println(trimtowidth(bigs[i], 8)); } }
Comments
Post a Comment