Я уверен, что есть более элегантный способ, но посмотрите, работает ли он?
import static org.junit.Assert.assertEquals;
import java.text.ChoiceFormat;
import java.text.DecimalFormat;
import java.text.FieldPosition;
import java.text.NumberFormat;
import java.text.ParsePosition;
import org.junit.Test;
public class NumberFormatTest {
@Test
public void testNumberFormat() {
NumberFormat nf = new MyNumberFormat();
assertEquals("-1234.4", nf.format(-1234.4));
assertEquals("0.0", nf.format(0));
assertEquals("+0.3", nf.format(0.3));
assertEquals("+12.0", nf.format(12));
}
}
class MyNumberFormat extends NumberFormat {
private DecimalFormat df = new DecimalFormat("0.0#");
private ChoiceFormat cf = new ChoiceFormat(new double[] { 0.0,
ChoiceFormat.nextDouble(0.0) }, new String[] { "", "+" });
@Override
public StringBuffer format(double number, StringBuffer toAppendTo,
FieldPosition pos) {
return toAppendTo.append(cf.format(number)).append(df.format(number));
}
@Override
public StringBuffer format(long number, StringBuffer toAppendTo,
FieldPosition pos) {
return toAppendTo.append(cf.format(number)).append(df.format(number));
}
@Override
public Number parse(String source, ParsePosition parsePosition) {
throw new UnsupportedOperationException();
}
}
Согласно Десятичный формат
Отрицательный подшаблон необязательный; если отсутствует, то положительный подшаблон с префиксом локализованного знака минус ('-' в большинстве локалей) используется как отрицательный подшаблон
Следовательно new DecimalFormat("0.0#")
эквивалентно new DecimalFormat("0.0#;-0.0#")
Так что это даст нам: -1234.5
и 1234.5
Теперь, чтобы добавить '+' к положительным числам, я использую ChoiceFormat
0.0 <= X < ChoiceFormat.nextDouble(0.0)
будет использовать формат выбора ""
. ChoiceFormat.nextDouble(0.0)
- наименьшее число, большее 0.0
.
ChoiceFormat.nextDouble(0.0) <= X < 1
будет использовать формат выбора "+"
.
Если совпадений нет, то используется либо первый, либо последний индекс, в зависимости от того, слишком мало или слишком велико число (X). Если массив пределов находится не в порядке возрастания, результаты форматирования будут неверными. ChoiceFormat также принимает \ u221E как эквивалент бесконечности (INF).
Следовательно
Double.NEGATIVE_INFINITY <= X < 0
будет использовать ""
.
1 <= X < Double.POSITIVE_INFINITY
будет использовать "+"
.