From 999101a608d32656ed43e49b49ac3b424485490f Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Sun, 7 Jun 2015 22:58:04 +0300 Subject: [PATCH] Exponential support in DecimalFormat --- .../classlib/java/text/TDecimalFormat.java | 60 ++++++++++++------- .../classlib/java/text/DecimalFormatTest.java | 10 ++++ 2 files changed, 50 insertions(+), 20 deletions(-) diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/text/TDecimalFormat.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/text/TDecimalFormat.java index 4f63f43de..2b75d02c9 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/text/TDecimalFormat.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/text/TDecimalFormat.java @@ -225,21 +225,20 @@ public class TDecimalFormat extends TNumberFormat { int mantissaLength = visibleExponent + 1; int significantSize = getMinimumIntegerDigits() + getMaximumFractionDigits(); - int exponentMultiplier = getMaximumIntegerDigits() - getMinimumIntegerDigits(); - if (exponentMultiplier > 0) { + int exponentMultiplier = getMaximumIntegerDigits() - getMinimumIntegerDigits() + 1; + if (exponentMultiplier > 1) { int delta = exponent - (exponent / exponentMultiplier) * exponentMultiplier; exponent -= delta; - exponentMultiplier -= delta; + visibleExponent -= delta; } else { - exponent -= getMinimumIntegerDigits(); - visibleExponent -= getMinimumIntegerDigits(); + exponent -= getMinimumIntegerDigits() - 1; + visibleExponent -= getMinimumIntegerDigits() - 1; } - int roundingPos = exponent + getMaximumFractionDigits(); - if (roundingPos < 0) { + if (significantSize < 0) { mantissa = 0; - } else if (roundingPos < mantissaLength) { - mantissa = applyRounding(mantissa, mantissaLength, roundingPos, positive); + } else if (significantSize < mantissaLength) { + mantissa = applyRounding(mantissa, mantissaLength, significantSize, positive); } int exponentPos = Math.max(visibleExponent, 0); @@ -248,12 +247,13 @@ public class TDecimalFormat extends TNumberFormat { buffer.append(Character.forDigit((int)(mantissa / mantissaDigitMask), 10)); mantissa %= mantissaDigitMask; } - for (int i = exponentPos; i >= visibleExponent; --i) { + for (int i = exponentPos - 1; i >= visibleExponent; --i) { buffer.append('0'); } 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()); int limit = Math.max(0, visibleExponent - significantSize); @@ -262,12 +262,12 @@ public class TDecimalFormat extends TNumberFormat { long mantissaDigitMask = POW10_ARRAY[i]; buffer.append(Character.forDigit((int)(mantissa / mantissaDigitMask), 10)); mantissa %= mantissaDigitMask; + ++count; if (mantissa == 0) { break; } - ++count; } - while (count-- < getMinimumFractionDigits()) { + while (count++ < requiredSize) { buffer.append('0'); } } @@ -277,12 +277,19 @@ public class TDecimalFormat extends TNumberFormat { exponent = -exponent; 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) { int exponentDigit = POW10_INT_ARRAY[i]; buffer.append(Character.forDigit(exponent / exponentDigit, 10)); 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) { @@ -420,15 +427,28 @@ public class TDecimalFormat extends TNumberFormat { } break; 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; 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; case HALF_EVEN: { - int digit = (int)((mantissa / rounding) % 10); - int delta = digit % 2 == 0 ? -1 : 1; - mantissa = ((mantissa + rounding / 2 + delta) / rounding) * rounding; + if (mantissa % rounding == rounding / 2) { + mantissa = (mantissa / rounding) * rounding; + if ((mantissa / rounding) % 2 != 0) { + mantissa += rounding; + } + } else { + mantissa = ((mantissa + rounding / 2) / rounding) * rounding; + } break; } } @@ -474,7 +494,7 @@ public class TDecimalFormat extends TNumberFormat { result += 2; value /= 100; } - if (value >= 10L) { + if (value >= 10) { result += 1; value /= 10; } diff --git a/teavm-tests/src/test/java/org/teavm/classlib/java/text/DecimalFormatTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/text/DecimalFormatTest.java index ee1420abe..75d21eab5 100644 --- a/teavm-tests/src/test/java/org/teavm/classlib/java/text/DecimalFormatTest.java +++ b/teavm-tests/src/test/java/org/teavm/classlib/java/text/DecimalFormatTest.java @@ -263,6 +263,16 @@ public class DecimalFormatTest { 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) { return new DecimalFormat(format, symbols); }