Точные расчеты Java — варианты использования

Я пытаюсь создать краткий обзор того, какие варианты точных вычислений у нас есть в JAVA + SQL. Пока нашел следующие варианты:

  1. использовать двойников, принимая их недостатки, не идти.
  2. use BigDecimals
    • using them in complicated formulas is problematic for me
  3. use String.format/Decimal.format to round doubles
    • do i need to round each variable in formula or just result to get BigDecimal precision?
    • как это можно подправить?
  4. use computed fields option in SQL.
    • drawback is that I'd need dynamic SQL to pull data from different tables + calculate fields on other calculated fields and that would get messy

любые другие варианты?

Постановка задачи: мне нужны точные финансовые расчеты, в которых использовались бы очень большие (миллиарды) и очень маленькие числа (0,0000004321), а также деление значений, которые очень похожи друг на друга, поэтому мне наверняка нужна точность BigDecimal.

С другой стороны, я хочу сохранить простоту использования, которую имеют двойники в функциях (я работаю с массивами из десятичных данных SQL), поэтому такие вычисления, как: (a[i] - b[i])/b[i] и т.д. и т. д., которые в дальнейшем используются в других расчетах. и я хотел бы, чтобы пользователи могли создавать свои собственные формулы по мере необходимости (используя общие математические операторы)

я стремлюсь использовать решение «форматирования» для String.format, но это делает код не очень читаемым (используя String.format() для каждой переменной...).

Большое спасибо за подсказку, как с этим бороться.


person mtx    schedule 26.04.2013    source источник
comment
Это может помочь... stackoverflow.com/questions/8636228/   -  person Maxx    schedule 26.04.2013
comment
Ваши требования нарушены дизайном, вернитесь к этапу анализа. Любой финансовый материал, в котором у вас нет фиксированного, обязательного и исчерпывающего определения, когда и как применять округление, гарантированно будет воспринят как неправильный расчет первым или вторым человеком, который его использует.   -  person Durandal    schedule 26.04.2013


Ответы (4)


Невозможно получить точность BigDecimal для double. double имеют двойную точность.

Если вы хотите гарантировать точные результаты, используйте BigDecimal.

Вы могли создать свой собственный вариант, используя long для хранения целой части и int для хранения дробной части, но зачем изобретать велосипед.

В любое время используйте double, чтобы избавиться от проблем с двойной точностью. Если вы используете их в одном месте, вы можете использовать их везде.

Даже если вы используете их только для представления данных из базы данных, данные будут округлены до двойной точности, и вы потеряете информацию.

person Boris the Spider    schedule 26.04.2013

Вы ничего не можете сделать, чтобы избежать ошибок с плавающей запятой в float и double. Здесь нет бесплатного сыра — используйте BigDecimal.

person Eugene    schedule 26.04.2013
comment
@Eugene, хорошо, спасибо за это замечание, но тогда давайте бросим вызов BigDecimals. Что потребуется, чтобы заставить приведенный ниже пример кода работать? // я знаю, что это неправильный синтаксис, но я бы хотел, чтобы он был таким ;) BigDecimal a = 1234.59053232; BigDecimalb = 1.000054530; Большой десятичный c; с = а/б; // или любая другая формула с "человеческим" синтаксисом? и на выходе получить точное значение c с заданной точностью, скажем, 4 цифры? - person mtx; 26.04.2013
comment
@mtx вы можете «скрыть» эти манипуляции в BigDecimal. Общие математические операторы могут быть сопоставлены с ENUM и предоставлять такие операции, как: DIVIDE, SQUARE и т. Д. У вас не может быть человеческого синтаксиса для нечеловеческого типа BigDecimal. Также в вашем конкретном примере операция деления будет выглядеть так: a.divide(b,4,RoundingMode.HALF_UP) - person Eugene; 26.04.2013

Из Effective Java (2-я редакция):

Правило 48. Избегайте float и double, если требуются точные ответы

  • Float и double не дают точных результатов и не должны использоваться там, где требуются точные результаты. Типы float и double особенно плохо подходят для денежных вычислений, потому что невозможно точно представить 0,1 (или любую другую отрицательную степень числа десять) как float или double.

  • Правильный способ решить эту проблему — использовать BigDecimal, int или long для денежных расчетов.

...

Альтернативой является использование int или long и самостоятельное отслеживание десятичной точки.

person user278064    schedule 26.04.2013

Если я понимаю ваш вопрос, вы хотите использовать типы данных с большей точностью, чем собственные типы Java, не теряя простого математического синтаксиса (например, / + * - и т. д.). Поскольку вы не можете перегружать операторы в Java, я думаю, что это невозможно.

person LionC    schedule 26.04.2013