Округление double по школьным правилам

171
04 февраля 2018, 00:49

Как добиться правильного "школьного" округления?

double lDoubleValue = 2,025;
Double lResult = new BigDecimal(lDoubleValue)
                    .setScale(2, RoundingMode.HALF_UP)
                    .doubleValue(); //2,02

При этом число 2,0251 округляется правильно до 2,03. И число 2,035 => 2,04 что полностью верно. Или использую не тот метод? Но, вроде, он самый-самый школьный.

Answer 1

Добро пожаловать в увлекательный мир двоичного представления действительных чисел в памяти компьютера! Тип данных double хранится в памяти согласно стандарту IEEE 754. Этот стандарт отводит на двоичное представление мантиссы (значащих разрядов) 53 бита. Этого далеко не всегда достаточно, чтобы точно представить конечную десятичную дробь в двоичном виде. Вообще, далеко не каждое действительное число, являющееся конечной дробью в десятичном виде, можно представить конечной дробью в двоичной системе счисления (например, 0.3). Поиграть с представлением десятичных чисел в двоичном виде в формате IEEE 754 можно здесь.

Приведённое вами в пример число 2.025 после записи в формате IEEE 754 для 64 разрядов превращается в 2.02499999999999991118215802999. Собственно, это и ломает округление. В документации для ROUND_HALF_UP сказано:

Rounding mode to round towards "nearest neighbor" unless both neighbors are equidistant, in which case round up.

Округление вверх происходит только если значение округляемого разряда эквидистантно (то есть находится на равном расстоянии) от соседей. В вашем же случае это не так, число меньше 0.5e-2, поэтому округляется вниз.

Избежать такого можно, если не использовать double или float в качестве промежуточного значения, а сразу оперировать с BigDecimal, который не подвержен подобным проблемам:

Double lResult = new BigDecimal("2.025").setScale(2, RoundingMode.HALF_UP).doubleValue();
READ ALSO
Продолжить программу при пустом поле EditText

Продолжить программу при пустом поле EditText

При наступлении условия if нужно передать int значение 1 для переменнойinputtext, которой должна присвоиться либо введенная пользователем информация...

169
Как добавить класс 'active' к текущей точке owl-carousel 2

Как добавить класс 'active' к текущей точке owl-carousel 2

Я использую слайдер owl carosel 2, мне нужно добавить класс 'active' к той точке, которая выбранаКак это можно сделать на js ?

253
Wordpress и Jquery. Одна кнопка для элементов

Wordpress и Jquery. Одна кнопка для элементов

Есть такая дилеммаПытаюсь создать под себя плагин карусели для WordPress

229