Используйте setRoundingMode
, явно задайте RoundingMode
, чтобы обрабатывать вашу проблему с полуточным раундом, а затем используйте шаблон формата для требуемого вывода.
Пример:
DecimalFormat df = new DecimalFormat("#.####");
df.setRoundingMode(RoundingMode.CEILING);
for (Number n : Arrays.asList(12, 123.12345, 0.23, 0.1, 2341234.212431324)) {
Double d = n.doubleValue();
System.out.println(df.format(d));
}
дает выход:
12
123.1235
0.23
0.1
2341234.2125
Это то, что я назвал бы ошибкой дизайна в спецификациях строки формата. Per docs ,
element_index ::= integer | index_string
, но, увы, -1
не является «целым числом» - это выражение. Унарный-минус-оператор даже не имеет особо высокого приоритета, так что, например, print(-2**2)
испускает -4
- еще одна распространенная проблема и, возможно, сбой в конструкции (оператор **
имеет более высокий приоритет, поэтому [1]
Все, что находится в этой строке в строке формата, которая не является целым числом (но, например, выражением), является символом изменения, который запрашивается младшим приоритетом унарного -
.
$ python3 -c "print('The last:{0[2+2]}'.format({'2+2': 23}))"
The last:23
Не уверен, стоит ли поднимать проблему в трассировке Python, но это, безусловно, несколько удивительное поведение :-(.
Здесь есть несколько проблем, как только вы начинаете копать:
Этот предмет называется «element_index», который определен как целое.
Проблема 1: если пользователи следуют ссылке из «integer» в справочное руководство по языку, они не будут знать, что -1 считается выражением, а не целочисленным. Кстати, любой соблазн сказать «работает как задокументированный» должен сначала увидеть пропозицию 7: -)
Предпочтительное решение: измените определение так, чтобы «element_index» мог иметь необязательный «-» перед целым числом.
Это целое число, верно? Не так быстро ... позже документы говорят, что «выражение формы [index]» выполняет поиск по индексу с помощью __getitem__()
»
Задача 3: Должен сказать« [element_index] »(индекс не определено).
Задача 4: Не все знают, что делает __getitem__()
. Нужны более четкие документы.
Таким образом, мы можем использовать здесь dict, а также целое число, не так ли? Да, с проблемой или двумя:
Элемент_индекс - целое число? Да, это работает с dict:
>>> "{0[2]}".format({2: 'int2'})
'int2'
Кажется, что мы также можем использовать нецелые строки, но для этого требуется более явная документация (проблема 5):
>>> "{0[foo]}".format({'foo': 'bar'})
'bar'
Но мы не можем использовать dict с ключом типа «2» (проблема 6):
>>> "{0[2]}".format({'2': 'str2'})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 2
>>> "{0['2']}".format({'2': 'str2'})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: "'2'"
Проблема 7: «Целое число» должно быть документировано как «десятичное целое» ... 0x22 и 0b11 обрабатываются как str, а 010 («окталинтегер») обрабатывается как 10, а не 8:
>>> "{0[010]}".format('0123456789abcdef')
'a'
Обновление: PEP 3101 сообщает истинную историю: «« Правила для разбора ключа элемента очень просты. Если он начинается с цифры, тогда он рассматривается как число, в противном случае он используется как строка.
Поскольку ключи не являются котировками, в ограничительной форме невозможно указать произвольные словарные ключи (например, строки «10» или «: -]») из строки формата. »" "
Правильно, это не сработает. Решение:
>>> 'The last:{0}'.format(a[-1])
'The last:3'
Я часто беру строки формата Python в качестве параметров конфигурации - с строкой формата, снабженной определенным, известным списком аргументов ключевого слова. Поэтому обращение к индексам списка переменной длины вперед или назад в строке формата - это именно то, что мне нужно.
Я только что написал этот хак, чтобы сделать работу с отрицательным индексированием:
string_to_tokenise = "Hello_world"
tokens = re.split(r"[^A-Z\d]+", string_to_tokenise, flags=re.I)
token_dict = {str(i) if i < 0 else i: tokens[i] for i in range(-len(tokens) + 1, len(tokens))}
print "{thing[0]} {thing[-1]}".format(thing=token_dict)
Результат:
Hello world
Итак, чтобы объяснить, вместо того, чтобы передавать в списке токенов, я создаю словарь со всеми необходимыми целыми ключами для индексации списка от 0 до len (..) - 1, и я также добавляю отрицательные целые ключи для индексации с конца от -1 до - (len (..) - 1), однако эти ключи преобразуются из целых чисел в строки, так как формат будет интерпретировать их.