Это похоже на проявление ошибки JDK-8174722 , зарегистрированной для JDK8 и все еще открытой с исправленной версией «tbd» (я вижу такое же поведение на JDK14). В этом отчете об ошибке округление 0.0001
до двух знаков после запятой неверно приводит к 0.00
, а не 0.01
.
Я попытался отследить этот расчет по исходному коду DecimalFormat
и обнаружил несколько предположения о количестве значащих цифр, сохраненные для совместимости, но, очевидно, являющиеся причиной подобных проблем. Моя догадка, основанная на исходном коде, заключается в том, что если первое di git после запрошенной точности равно 0 (или достаточно близко), функция округляется в меньшую сторону. Такое поведение противоречит документации, в которой четко указано иное.
Если бы это было легко исправить, я полагаю, связанная ошибка была бы исправлена задолго до этого, но она также имеет низкий приоритет.
Как предполагалось в комментариях, использование функций Math.ceil()
, Math.floor()
и Math.round()
обеспечит более предсказуемые / согласованные результаты и будет достаточным для большинства случаев использования.
В своих комментариях вы предложили пользователь предоставил RoundingMode
, поэтому, если вам нужно прямое применение этого перечисления, MCVE отчета об ошибке включает обходной путь с использованием BigDecimal.setScale()
. @ Андреас опубликовал приложение этого обходного пути в этот комментарий , чтобы создать эту строку:
// Note: this ignores Locale
BigDecimal.valueOf(number).setScale(0, RoundingMode.UP).toPlainString();
Другой вариант с использованием DecimalFormat
позволит изменить настройки локали и будет:
df.format(BigDecimal.valueOf(number).setScale(0, RoundingMode.UP));
Обратите внимание, что, поскольку вы использовали бы округление в setScale()
, вам не нужно также использовать его в DecimalFormat
.