Index: Formatter.java =================================================================== --- Formatter.java (revision 454458) +++ Formatter.java (working copy) @@ -28,6 +28,8 @@ import java.io.UnsupportedEncodingException; import java.math.BigDecimal; import java.math.BigInteger; +import java.math.MathContext; +import java.math.RoundingMode; import java.nio.CharBuffer; import java.nio.charset.Charset; import java.security.AccessController; @@ -1513,8 +1515,21 @@ if (null == arg) { return transformFromNull(); } + + if ('a' != Character.toLowerCase(currentConversionType)) { + formatToken + .setPrecision(formatToken.isPrecisionSet() ? formatToken + .getPrecision() + : FormatToken.DEFAULT_PRECISION); + } - if (!(arg instanceof Float || arg instanceof Double || arg instanceof BigDecimal)) { + if (arg instanceof Float) + arg = round((Float)arg, formatToken.getPrecision()); + else if (arg instanceof Double) + arg = round((Double)arg, formatToken.getPrecision()); + else if (arg instanceof BigDecimal) + arg = round((BigDecimal)arg, formatToken.getPrecision()); + else { throw new IllegalFormatConversionException( currentConversionType, arg.getClass()); } @@ -1524,12 +1539,6 @@ return specialNumberResult; } - if ('a' != Character.toLowerCase(currentConversionType)) { - formatToken - .setPrecision(formatToken.isPrecisionSet() ? formatToken - .getPrecision() - : FormatToken.DEFAULT_PRECISION); - } // output result FloatUtil floatUtil = new FloatUtil(result, formatToken, (DecimalFormat) NumberFormat.getInstance(locale), arg); @@ -1617,6 +1626,27 @@ dateTimeUtil.transform(formatToken, calendar, result); return padding(result, startIndex); } + + private Float round(float original, int precision) { + float divisor = (float)Math.pow(10.0, (double)precision); + float newValue = StrictMath.abs(original * divisor); + + return (StrictMath.round(newValue) / divisor * Math.signum(original)); + } + + private Double round(double original, int precision) { + double divisor = Math.pow(10.0, (double)precision); + double newValue = StrictMath.abs(original * divisor); + + return (StrictMath.round(newValue) / divisor * Math.signum(original)); + } + + private BigDecimal round(BigDecimal original, int precision) { + BigDecimal newValue = original.scaleByPowerOfTen(precision); + newValue = newValue.round(MathContext.UNLIMITED); + + return (newValue.scaleByPowerOfTen(-1 * precision)); + } } private static class FloatUtil {