1 32 package net.sf.retrotranslator.runtime.format; 33 34 import java.math.*; 35 import java.text.DecimalFormatSymbols ; 36 37 40 abstract class FloatingPointConversion extends NumericConversion { 41 42 protected abstract void printf(FormatContext context, boolean negative, BigDecimal argument); 43 44 protected void printf(FormatContext context) { 45 Object argument = context.getArgument(); 46 if (argument instanceof Double ) { 47 printf(context, (Double ) argument); 48 } else if (argument instanceof Float ) { 49 printf(context, (Float ) argument); 50 } else if (argument == null) { 51 context.writeRestricted(String.valueOf(argument)); 52 } else if (argument instanceof BigDecimal) { 53 BigDecimal bigDecimal = (BigDecimal) argument; 54 printf(context, bigDecimal.signum() < 0, bigDecimal.abs()); 55 } else { 56 throw context.getConversionException(); 57 } 58 } 59 60 private void printf(FormatContext context, double argument) { 61 if (!printSpecialNumber(context, argument)) { 62 printf(context, Double.doubleToLongBits(argument) < 0, BigDecimal.valueOf(Math.abs(argument))); 63 } 64 } 65 66 protected static void printComputerizedScientificNumber(FormatContext context, boolean negative, 67 BigDecimal argument, int precision) { 68 String unscaled = argument.unscaledValue().toString(); 69 StringBuilder builder = new StringBuilder (); 70 builder.append(unscaled.charAt(0)); 71 if (precision > 0 || context.isFlag('#')) { 72 builder.append('.'); 73 } 74 if (precision < unscaled.length()) { 75 builder.append(unscaled.substring(1, precision + 1)); 76 } else { 77 builder.append(unscaled.substring(1)); 78 appendZeros(builder, precision + 1 - unscaled.length()); 79 } 80 int exponent = unscaled.equals("0") ? 0 : unscaled.length() - argument.scale() - 1; 81 builder.append('e').append(exponent < 0 ? '-' : '+'); 82 int absoluteExponent = Math.abs(exponent); 83 if (absoluteExponent < 10) { 84 builder.append('0'); 85 } 86 builder.append(absoluteExponent); 87 printNumber(context, negative, null, builder, context.getSymbols(false)); 88 } 89 90 protected static void printDecimalNumber(FormatContext context, boolean negative, 91 BigDecimal argument, boolean localized) { 92 String unscaled = argument.unscaledValue().toString(); 93 String integerPart = "0"; 94 String fractionPart = ""; 95 int separatorIndex = unscaled.length() - argument.scale(); 96 if (separatorIndex < 0) { 97 fractionPart = appendZeros(new StringBuilder (), -separatorIndex).append(unscaled).toString(); 98 } else if (separatorIndex == 0) { 99 fractionPart = unscaled; 100 } else if (separatorIndex < unscaled.length()) { 101 integerPart = unscaled.substring(0, separatorIndex); 102 fractionPart = unscaled.substring(separatorIndex); 103 } else if (separatorIndex == unscaled.length()) { 104 integerPart = unscaled; 105 } else { 106 integerPart = appendZeros(new StringBuilder (unscaled), separatorIndex - unscaled.length()).toString(); 107 } 108 StringBuilder builder = new StringBuilder (); 109 DecimalFormatSymbols symbols = context.getSymbols(localized); 110 appendNumber(builder, integerPart, context.isFlag(','), symbols); 111 if (fractionPart.length() > 0 || context.isFlag('#')) { 112 builder.append(symbols.getDecimalSeparator()); 113 } 114 appendNumber(builder, fractionPart, false, symbols); 115 printNumber(context, negative, null, builder, symbols); 116 } 117 118 protected static StringBuilder appendZeros(StringBuilder builder, int count) { 119 for (int i = 0; i < count; i++) { 120 builder.append('0'); 121 } 122 return builder; 123 } 124 125 protected static BigDecimal round(BigDecimal decimal, int shift) { 126 int scale = decimal.scale() - shift; 127 return scale >= 0 ? 128 decimal.setScale(scale, BigDecimal.ROUND_HALF_UP) : 129 decimal.movePointRight(scale).setScale(0, BigDecimal.ROUND_HALF_UP).movePointLeft(scale); 130 } 131 132 public static class ComputerizedScientificConversion extends FloatingPointConversion { 133 134 public void format(FormatContext context) { 135 context.checkFlags(); 136 context.assertNoFlag(','); 137 printf(context); 138 } 139 140 protected void printf(FormatContext context, boolean negative, BigDecimal argument) { 141 int shift = argument.unscaledValue().toString().length() - context.getNumberPrecision() - 1; 142 printComputerizedScientificNumber(context, negative, round(argument, shift), context.getNumberPrecision()); 143 } 144 } 145 146 public static class DecimalConversion extends FloatingPointConversion { 147 148 public void format(FormatContext context) { 149 context.checkWidth(); 150 context.checkFlags(); 151 printf(context); 152 } 153 154 protected void printf(FormatContext context, boolean negative, BigDecimal argument) { 155 BigDecimal roundedArgument = argument.setScale(context.getNumberPrecision(), BigDecimal.ROUND_HALF_UP); 156 printDecimalNumber(context, negative, roundedArgument, true); 157 } 158 } 159 160 public static class GeneralScientificConversion extends FloatingPointConversion { 161 162 public void format(FormatContext context) { 163 context.checkFlags(); 164 context.assertNoFlag('#'); 165 printf(context); 166 } 167 168 protected void printf(FormatContext context, boolean negative, BigDecimal argument) { 169 int precision = Math.max(context.getNumberPrecision(), 1); 170 BigDecimal roundedArgument = round(argument, argument.unscaledValue().toString().length() - precision); 171 if (roundedArgument.compareTo(new BigDecimal(BigInteger.ONE, 4)) >= 0 && 172 roundedArgument.compareTo(BigDecimal.ONE.movePointRight(precision)) < 0) { 173 printDecimalNumber(context, negative, roundedArgument, context.getArgument() instanceof BigDecimal); 174 } else { 175 printComputerizedScientificNumber(context, negative, roundedArgument, precision - 1); 176 } 177 } 178 179 } 180 181 } 182 | Popular Tags |