Бьюсь об заклад, здесь на SO был аналогичный вопрос, я просто не мог его найти. Вопрос заключается в исправлении неточности математики Java, когда я получаю, например, число, подобное 235.00000002
или 9875.999999997
. Конечно, черт возьми, для человека эти два на самом деле означают 235
и 9876
, когда дается определенный порог точности, давайте назовем его «5 нулей или девяток».
Но дело не только в цифрах справа от запятой, это же правило должно применяться и к таким числам, как 23500000001.0
и 5699999999.0
.
Есть идеи/библиотеки?
Обновление: Похоже, я ошибался, говоря, что это известная тема, и через несколько минут появится кто-нибудь с известной библиотекой. Итак, вот логика, которую я ожидаю: для данного числа, когда в его строковом представлении встречаются N последовательных нулей или девяток, эти нули и девятки округляются вместе с остальной частью числа справа от самого правого «0» или « 9". Например, когда N=5, число 239999995.546
становится 240000000.0
, число 34.0000007
становится 34
, а 340000.007
становится 340000
.
Обновление 2. Вот что бывает, когда спешишь или не уделяешь должного внимания вопросу. Извиняюсь. Я говорю о "человеческом" округлении. Хорошим примером может служить сравнение вывода df
и df -h
на Linux-боксе. Что касается «неточности», о которой я говорил, запустите следующий код:
double d = 1000.0;
double mult = 0.12351665;
System.out.println(d * mult / mult);
Ответ определенно не тот, который вы бы показали в корзине. В моем случае дело обстоит еще хуже, я имею дело не только с деньгами, это может быть что угодно - проценты, большие числа, мелкие дроби, и все это в результате относительно тяжелых математических вычислений. Так что я говорю об округлении, которое имеет смысл для человека.
Я уже закончил с кодом, но все еще есть шанс, что кто-то сделал это лучше.
239999995.546
хуже, чем239989995.546
? Но, возможно, вам поможет что-то вроде этого вопроса: stackoverflow.com/questions/7906996/ - person Sebastian Höffner   schedule 26.04.2014240000000.0
сохраняет.0
, а340000
и34
нет? Также вам может помочь научная нотация, предоставленная Formatter%e
, она дает2.400000e+08
для239999995.546
- person Sebastian Höffner   schedule 26.04.2014.0
, его можно опустить, это просто способ показать, что он все еще двойной. - person andbi   schedule 26.04.2014BigDecimal
, кажется именно тем, что вам нужно. Проблема, с которой вы сталкиваетесь, связана с точностью с плавающей запятой, а не с форматированием результатов или чем-то еще. Попробуйте1000.0 * 0.123 / 0.123
и у вас не будет проблем с получением в результате999.99999
. Тем не менее, вы говорите, что у вас есть готовый код, но, возможно, кто-то мог бы сделать его лучше — как насчет того, чтобы вы предоставили нам код, и мы могли бы посмотреть, сможем ли мы его улучшить? - person Sebastian Höffner   schedule 26.04.2014System.out.println(simplify(d*mult/mult));
печатает1000
. - person Sebastian Höffner   schedule 26.04.2014BigDecimal
только для валют - и ваши примеры процентов, больших чисел, мелких дробей и т. д. идеально подходят для приложений для BigDecimals. - person Sebastian Höffner   schedule 26.04.2014