Я не могу понять поведение режима округления BigDecimal HALF_EVEN, когда ни одна из отбрасываемых цифр не превышает 2 (не ноль).
Согласно документации, при округлении HALF_EVEN, когда левая цифра отбрасываемой цифры четная , это случай HALF_DOWN, поэтому левая цифра не увеличивается. Таким образом, «1,3651» со шкалой 2 должно дать «1,36», но результат будет «1,37». Глядя на код BigDecimal, кажется, что если число, образованное отбрасываемыми цифрами, больше 50, оно добавляет приращение, и поэтому я получаю результат как «1,37».
private static int longCompareMagnitude(long x, long y) {
if (x < 0)
x = -x;
if (y < 0)
y = -y;
return (x < y) ? -1 : ((x == y) ? 0 : 1);
}
Пояснение X и Y в приведенном выше фрагменте кода
x : 2*(нет, образованное цифрами, которые нужно отбросить).
например. 1,3753 и масштаб 2, здесь x будет 53*2 = 106
y : это ведро по длине отброшенных цифр [1,10,100]. Y здесь 100
int drop = checkScale((long) oldScale - newScale);
// old scale is precision on current number(decimal places after . : 4)
y = LONG_TEN_POWERS_TABLE[drop]
Таким образом, случай x==y — это когда отбрасываемая цифра равна 5 или 50 и т. д.
в противном случае, если число, образованное отброшенными цифрами, больше 50, оно всегда будет добавлять 1 . поэтому приведенные ниже случаи, похоже, работают согласно коду. Но в документации указано, что это случай HALF_DOWN и, следовательно, не следует увеличивать[HALF_UP]
Чтобы убедиться в этом, я написал следующие примеры. может кто-нибудь объяснить поведение последних двух записей, где результат помечен как ложный.
Версия Java: OpenLogic-OpenJDK (сборка 11.0.16+8), Corretto-17.0.12.7 .1
@Test
fun bigDecimalTest() {
printResult("Round up ", "1.176", "1.18", 2)
//4 being dropped is less than 5, doesn't qualify for round up
printResult("Round down", "1.174", "1.17", 2)
println("Equidistant round off with HALF EVEN rounding")
printResult("HALF up case", "1.175", "1.18", 2)
printResult("HALF up case", "1.3753", "1.38", 2)
printResult("HALF down case", "1.365", "1.36", 2)
printResult("HALF down case with 2 digits dropped", "1.3650", "1.36", 2)
println("half down not happening when number formed by digits to be dropped is 5/50")
printResult("HALF down case with 2 digits dropped", "1.3651", "1.36", 2)
printResult("HALF down case with 2 digits dropped", "1.3653", "1.36", 2)
}
private fun printResult(message: String, input: String, expected: String, scale: Int) {
val actual = BigDecimal(input).setScale(scale, RoundingMode.HALF_EVEN)
val result = BigDecimal(expected) == actual
println("$message, scale: $scale: input: $input, expected :$expected, actual= $actual, Matched= $result")
}
Вывод:
Round up , scale: 2: input: 1.176, expected :1.18, actual= 1.18, Matched= true
Round down, scale: 2: input: 1.174, expected :1.17, actual= 1.17, Matched= true
Equidistant round off with HALF EVEN rounding
HALF up case, scale: 2: input: 1.175, expected :1.18, actual= 1.18, Matched= true
HALF up case, scale: 2: input: 1.3753, expected :1.38, actual= 1.38, Matched= true
HALF down case, scale: 2: input: 1.365, expected :1.36, actual= 1.36, Matched= true
HALF down case with 2 digits dropped, scale: 2: input: 1.3650, expected :1.36, actual= 1.36, Matched= true
half down not happening when number formed by digits to be dropped is 5/50
HALF down case with 2 digits dropped, scale: 2: input: 1.3651, expected :1.36, actual= 1.37, Matched= false
HALF down case with 2 digits dropped, scale: 2: input: 1.3653, expected :1.36, actual= 1.37, Matched= false
Подробнее здесь: https://stackoverflow.com/questions/792 ... -dropped-a
Режим округления BigDecimal HALF_EVEN не работает, если ни одна из отбрасываемых цифр не превышает 1 ⇐ JAVA
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение