ICU4J CompactDecimalFormat версия 56 setMaximumFractionDigits, setMaximumIntegerDigits не работает, но setMaximumSignificantDigits работает - PullRequest
0 голосов
/ 17 марта 2019

Я использую ICU4J CompactDecimalFormat через android.icu.text.CompactDecimalFormat. В версиях Android 24 и 25 , что соответствует ICU версии 56, я не вижу ожидаемого поведения при использовании setMaximumFractionDigits или setMaximumIntegerDigits. Тем не менее, setMaximumSignificantDigits работает, как и ожидалось, я просто должен сначала сделать математику перед его использованием:

long number = // get a number from somehwere
CompactDecimalFormat compactDecimalFormat = CompactDecimalFormat.getInstance(Locale.getDefault(), CompactStyle.SHORT);
compactDecimalFormat.setMaximumSignificantDigits(
  getMaximumSignificantDigitsFor3IntegerDigitsAnd1FractionDigit(number)
)
String formatted = compactDecimalFormat.format(number);

, где getMaximumSignificantDigitsFor3IntegerDigitsAnd1FractionDigit:

private int getMaximumSignificantDigitsFor3IntegerDigitsAnd1FractionDigit(long number) {
    if (thousands >= 1000) {
      val millions = number / 1_000_000L;
      if (millions >= 1000) {
        val billions = number / 1_000_000_000L;
        if (billions >= 1000) {
          // 1,234.5 B or 1.2345T
          return 5;
        } else if (billions >= 100) {
          // 123.4 B
          return 4;
        } else if (billions >= 10) {
          // 12.3 B
          return 3;
        } else if (billions >= 1) {
          // 1.2 B
          return 2;
        } else {
          // should never happen, use 4 to be safe
          return 4;
        }
      } else if (millions >= 100) {
        // 123.4M
        return 4;
      } else if (millions >= 10) {
        // 12.3M
        return 3;
      } else if (millions >= 1) {
        // 1.2M
        return 2;
      } else {
        // shouldn't happen, use 4 to be safe
        return 4;
      }
    } else if (thousands >= 100) {
      // 123.4K
      return 4;
    } else if (thousands >= 10) {
      // 12.3K
      return 3;
    } else if (thousands >= 1) {
      // 1.2K or 1200
      return 2;
    } else {
      // 123 exactly, no fractional component
      return 3;
    }
}

Я ничего не могу найти в документации ICU4J CompactDecimalFormat о неиспользовании setMaximumIntegerDigits или setMaximumIntegerDigits.

Я создал gist, который демонстрирует кучу соответствующих тестовых случаев. Я включил случай с сотней тысяч ниже:

// Fails on API 24. Works on API 28
@Test
public void testSignificantDigitsUsedFalseThenSetMaximumIntegerDigitsThenSetMaximumFractionDigitsForHundredThousandish() {
    testObject.setSignificantDigitsUsed(false);
    testObject.setMaximumIntegerDigits(3);
    testObject.setMaximumFractionDigits(1);

    final String actual = testObject.format(123_456);
    assertEquals("123.5K", actual); // rounding
    // API 24: "100K"
    // API 28: "123.5K"
}

// Fails on API 24. Works on API 28
@Test
public void testSetMaximumIntegerDigitsThenSetMaximumFractionDigitsThenSetSignificantDigitsUsedFalseHundredThousandish() {
    testObject.setMaximumIntegerDigits(3);
    testObject.setMaximumFractionDigits(1);
    testObject.setSignificantDigitsUsed(false);

    final String actual = testObject.format(123_456);
    assertEquals("123.5K", actual); // rounding
    // API 24: "100K"
    // API 28: "123.5K"
}

// Works on API 24 and API 28
@Test
public void testSetMaximumSignificantDigitsHundredThousandish() {
    testObject.setMaximumSignificantDigits(4);

    final String actual = testObject.format(123_456);
    assertEquals("123.5K", actual); // rounding
}

Есть идеи, почему это не работает в Android API 24 (ICU 56), но работает в Android API 28 (ICU 60.2)?

...