Implementing DecimalFormat

This commit is contained in:
Alexey Andreev 2015-06-07 18:02:38 +03:00
parent 87d8c3406c
commit 27da14d827
2 changed files with 82 additions and 1 deletions

View File

@ -30,6 +30,8 @@ public class TDecimalFormat extends TNumberFormat {
1_000_0000, 1_0000_0000, 1_0_0000_0000, 1_00_0000_0000L, 1_000_0000_0000L, 1_0000_0000_0000L,
1_0_0000_0000_0000L, 1_00_0000_0000_0000L, 1_000_0000_0000_0000L, 1_0000_0000_0000_0000L,
1_0_0000_0000_0000_0000L, 1_00_0000_0000_0000_0000L };
private static final int[] POW10_INT_ARRAY = { 1, 10, 100, 1000, 1_0000, 1_0_0000, 1_00_0000,
1_000_0000, 1_0000_0000, 1_0_0000_0000 };
private static final double[] POW10_FRAC_ARRAY = { 1E1, 1E2, 1E4, 1E8, 1E16, 1E32, 1E64, 1E128, 1E256 };
private static final double[] POWM10_FRAC_ARRAY = { 1E-1, 1E-2, 1E-4, 1E-8, 1E-16, 1E-32, 1E-64, 1E-128, 1E-256 };
private static final int DOUBLE_MAX_EXPONENT = 308;
@ -250,7 +252,37 @@ public class TDecimalFormat extends TNumberFormat {
buffer.append('0');
}
significantSize -= visibleExponent;
significantSize -= mantissaLength - visibleExponent;
if (getMinimumIntegerDigits() > 0 || (mantissa != 0 && significantSize > 0)) {
buffer.append(symbols.getDecimalSeparator());
int limit = Math.max(0, visibleExponent - significantSize);
int count = 0;
for (int i = visibleExponent - 1; i >= limit; --i) {
long mantissaDigitMask = POW10_ARRAY[i];
buffer.append(Character.forDigit((int)(mantissa / mantissaDigitMask), 10));
mantissa %= mantissaDigitMask;
if (mantissa == 0) {
break;
}
++count;
}
while (count-- < getMinimumFractionDigits()) {
buffer.append('0');
}
}
buffer.append(symbols.getExponentSeparator());
if (exponent < 0) {
exponent = -exponent;
buffer.append(symbols.getMinusSign());
}
int exponentLength = Math.max(exponentDigits, fastLn10(exponent));
for (int i = exponentLength - 1; i >= 0; --i) {
int exponentDigit = POW10_INT_ARRAY[i];
buffer.append(Character.forDigit(exponent / exponentDigit, 10));
exponent %= exponentDigit;
}
}
private void formatRegular(long mantissa, int exponent, StringBuffer buffer) {
@ -428,6 +460,27 @@ public class TDecimalFormat extends TNumberFormat {
return result;
}
private int fastLn10(int value) {
int result = 0;
if (value >= 1_0000_0000) {
result += 8;
value /= 1_0000_0000;
}
if (value >= 1_0000) {
result += 4;
value /= 1_0000;
}
if (value >= 100) {
result += 2;
value /= 100;
}
if (value >= 10L) {
result += 1;
value /= 10;
}
return result;
}
private MantissaAndExponent getMantissaAndExponent(double value) {
long mantissaPattern = POW10_ARRAY[17];
int exp = 0;

View File

@ -235,6 +235,34 @@ public class DecimalFormatTest {
assertEquals("-9223372036854775808", format.format(-9223372036854775808L));
}
@Test
public void formatsExponent() {
DecimalFormat format = createFormat("000E0");
assertEquals("230E-1", format.format(23));
assertEquals("230E0", format.format(230));
assertEquals("230E1", format.format(2300));
assertEquals("123E1", format.format(1234));
format = createFormat("0.00E0");
assertEquals("2.00E1", format.format(20));
assertEquals("2.30E1", format.format(23));
assertEquals("2.30E2", format.format(230));
assertEquals("1.23E3", format.format(1234));
format = createFormat("000000000000000000000.00E0");
assertEquals("230000000000000000000.00E-19", format.format(23));
format = createFormat("0.0000000000000000000000E0");
assertEquals("2.3000000000000000000000E1", format.format(23));
format = createFormat("0.0##E0");
assertEquals("1.0E0", format.format(1));
assertEquals("1.2E1", format.format(12));
assertEquals("1.23E2", format.format(123));
assertEquals("1.234E3", format.format(1234));
assertEquals("1.234E4", format.format(12345));
}
private DecimalFormat createFormat(String format) {
return new DecimalFormat(format, symbols);
}