Я использую 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
)?