Exponential support in DecimalFormat

This commit is contained in:
Alexey Andreev 2015-06-07 22:58:04 +03:00
parent 27da14d827
commit 999101a608
2 changed files with 50 additions and 20 deletions

View File

@ -225,21 +225,20 @@ public class TDecimalFormat extends TNumberFormat {
int mantissaLength = visibleExponent + 1; int mantissaLength = visibleExponent + 1;
int significantSize = getMinimumIntegerDigits() + getMaximumFractionDigits(); int significantSize = getMinimumIntegerDigits() + getMaximumFractionDigits();
int exponentMultiplier = getMaximumIntegerDigits() - getMinimumIntegerDigits(); int exponentMultiplier = getMaximumIntegerDigits() - getMinimumIntegerDigits() + 1;
if (exponentMultiplier > 0) { if (exponentMultiplier > 1) {
int delta = exponent - (exponent / exponentMultiplier) * exponentMultiplier; int delta = exponent - (exponent / exponentMultiplier) * exponentMultiplier;
exponent -= delta; exponent -= delta;
exponentMultiplier -= delta; visibleExponent -= delta;
} else { } else {
exponent -= getMinimumIntegerDigits(); exponent -= getMinimumIntegerDigits() - 1;
visibleExponent -= getMinimumIntegerDigits(); visibleExponent -= getMinimumIntegerDigits() - 1;
} }
int roundingPos = exponent + getMaximumFractionDigits(); if (significantSize < 0) {
if (roundingPos < 0) {
mantissa = 0; mantissa = 0;
} else if (roundingPos < mantissaLength) { } else if (significantSize < mantissaLength) {
mantissa = applyRounding(mantissa, mantissaLength, roundingPos, positive); mantissa = applyRounding(mantissa, mantissaLength, significantSize, positive);
} }
int exponentPos = Math.max(visibleExponent, 0); int exponentPos = Math.max(visibleExponent, 0);
@ -248,12 +247,13 @@ public class TDecimalFormat extends TNumberFormat {
buffer.append(Character.forDigit((int)(mantissa / mantissaDigitMask), 10)); buffer.append(Character.forDigit((int)(mantissa / mantissaDigitMask), 10));
mantissa %= mantissaDigitMask; mantissa %= mantissaDigitMask;
} }
for (int i = exponentPos; i >= visibleExponent; --i) { for (int i = exponentPos - 1; i >= visibleExponent; --i) {
buffer.append('0'); buffer.append('0');
} }
significantSize -= mantissaLength - visibleExponent; significantSize -= mantissaLength - visibleExponent;
if (getMinimumIntegerDigits() > 0 || (mantissa != 0 && significantSize > 0)) { int requiredSize = significantSize - (getMaximumFractionDigits() - getMinimumFractionDigits());
if (requiredSize > 0 || (mantissa != 0 && significantSize > 0)) {
buffer.append(symbols.getDecimalSeparator()); buffer.append(symbols.getDecimalSeparator());
int limit = Math.max(0, visibleExponent - significantSize); int limit = Math.max(0, visibleExponent - significantSize);
@ -262,12 +262,12 @@ public class TDecimalFormat extends TNumberFormat {
long mantissaDigitMask = POW10_ARRAY[i]; long mantissaDigitMask = POW10_ARRAY[i];
buffer.append(Character.forDigit((int)(mantissa / mantissaDigitMask), 10)); buffer.append(Character.forDigit((int)(mantissa / mantissaDigitMask), 10));
mantissa %= mantissaDigitMask; mantissa %= mantissaDigitMask;
++count;
if (mantissa == 0) { if (mantissa == 0) {
break; break;
} }
++count;
} }
while (count-- < getMinimumFractionDigits()) { while (count++ < requiredSize) {
buffer.append('0'); buffer.append('0');
} }
} }
@ -277,12 +277,19 @@ public class TDecimalFormat extends TNumberFormat {
exponent = -exponent; exponent = -exponent;
buffer.append(symbols.getMinusSign()); buffer.append(symbols.getMinusSign());
} }
int exponentLength = Math.max(exponentDigits, fastLn10(exponent)); int exponentLength = Math.max(exponentDigits, fastLn10(exponent) + 1);
for (int i = exponentLength - 1; i >= 0; --i) { for (int i = exponentLength - 1; i >= 0; --i) {
int exponentDigit = POW10_INT_ARRAY[i]; int exponentDigit = POW10_INT_ARRAY[i];
buffer.append(Character.forDigit(exponent / exponentDigit, 10)); buffer.append(Character.forDigit(exponent / exponentDigit, 10));
exponent %= exponentDigit; exponent %= exponentDigit;
} }
// Add suffix
if (positive) {
buffer.append(positiveSuffix != null ? positiveSuffix : "");
} else {
buffer.append(negativeSuffix != null ? negativeSuffix : positiveSuffix != null ? positiveSuffix : "");
}
} }
private void formatRegular(long mantissa, int exponent, StringBuffer buffer) { private void formatRegular(long mantissa, int exponent, StringBuffer buffer) {
@ -420,15 +427,28 @@ public class TDecimalFormat extends TNumberFormat {
} }
break; break;
case HALF_DOWN: case HALF_DOWN:
mantissa = ((mantissa + rounding / 2 - 1) / rounding) * rounding; if (mantissa % rounding == rounding / 2) {
mantissa = (mantissa / rounding) * rounding;
} else {
mantissa = ((mantissa + rounding / 2) / rounding) * rounding;
}
break; break;
case HALF_UP: case HALF_UP:
mantissa = ((mantissa + rounding / 2 + 1) / rounding) * rounding; if (mantissa % rounding == rounding / 2) {
mantissa = (mantissa / rounding) * rounding + rounding;
} else {
mantissa = ((mantissa + rounding / 2) / rounding) * rounding;
}
break; break;
case HALF_EVEN: { case HALF_EVEN: {
int digit = (int)((mantissa / rounding) % 10); if (mantissa % rounding == rounding / 2) {
int delta = digit % 2 == 0 ? -1 : 1; mantissa = (mantissa / rounding) * rounding;
mantissa = ((mantissa + rounding / 2 + delta) / rounding) * rounding; if ((mantissa / rounding) % 2 != 0) {
mantissa += rounding;
}
} else {
mantissa = ((mantissa + rounding / 2) / rounding) * rounding;
}
break; break;
} }
} }
@ -474,7 +494,7 @@ public class TDecimalFormat extends TNumberFormat {
result += 2; result += 2;
value /= 100; value /= 100;
} }
if (value >= 10L) { if (value >= 10) {
result += 1; result += 1;
value /= 10; value /= 10;
} }

View File

@ -263,6 +263,16 @@ public class DecimalFormatTest {
assertEquals("1.234E4", format.format(12345)); assertEquals("1.234E4", format.format(12345));
} }
@Test
public void formatsExponentWithMultiplier() {
DecimalFormat format = createFormat("##0.00E0");
assertEquals("2.30E0", format.format(2.3));
assertEquals("23.0E0", format.format(23));
assertEquals("230E0", format.format(230));
assertEquals("2.30E3", format.format(2300));
assertEquals("23.0E3", format.format(23000));
}
private DecimalFormat createFormat(String format) { private DecimalFormat createFormat(String format) {
return new DecimalFormat(format, symbols); return new DecimalFormat(format, symbols);
} }