Какой режим округления использовать для манипулирования валютой в java?

Я прочитал на сайте Java, чтобы использовать BigDecimal для валют. http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html

Но какой режим округления мы должны использовать? который является наиболее подходящим и наиболее широко используемым


person Ahsan Abid    schedule 21.11.2011    source источник


Ответы (5)


Нет "правильного" режима, все зависит от бизнес-кейса. Примеры:

  • При расчете годовых налогов дроби часто обрезаются (RoundingMode.FLOOR).
  • При расчете бонуса вы можете всегда округлять в пользу клиента (RoundingMode.CEILING).
  • Для налогов в счете обычно округляют HALF_UP.
  • При выполнении сложных финансовых симуляций округление вообще не требуется.

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

Чтобы получить лучший ответ, вы должны сообщить нам, чего вы хотите достичь.

Тем не менее, BigDecimal является правильным типом для использования в Java, потому что он может сохранять любую точность, а также позволяет вам выбрать режим округления, наиболее подходящий для вашего случая.

person Aaron Digulla    schedule 21.11.2011

В большинстве случаев BigDecimal является единственным допустимым выбором для валют. Но выбор стратегии округления не столь очевиден.

По умолчанию используется HALF_EVEN, что происходит с быть хорошим выбором. Этот алгоритм известен как банковское округление (см. обсуждение здесь).

Другой распространенной стратегией является HALF_UP. более интуитивно понятен, но имеет несколько худшие статистические характеристики.

Также обратите внимание, что во многих случаях (особенно в банковском деле и страховании) стратегия округления будет диктоваться бизнес-требованиями, часто разными для разных вариантов использования.

person Tomasz Nurkiewicz    schedule 21.11.2011
comment
Вы должны добавить, что HALF_EVEN неэффективен. - person Jus12; 14.11.2017

Обычно вы используете округление «половина вверх», например:

myBigDecimal.setScale(2, RoundingMode.HALF_UP);

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

person Amos M. Carpenter    schedule 21.11.2011

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

person Sqeezer    schedule 21.11.2011

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

При отображении суммы разделите ее на соответствующий коэффициент, чтобы получить нецелую часть.

person Brett Walker    schedule 21.11.2011
comment
На самом деле, BigDecimals совершенно безопасны и точны при правильном использовании. Только не используйте double или float. - person Amos M. Carpenter; 21.11.2011
comment
+1: @aaamos, за исключением того, что большинство инвестиционных банков используют double, иногда int/long. особенно тех, кто использует C/C++, у него нет встроенного десятичного типа. - person Peter Lawrey; 21.11.2011
comment
@Peter: еще один намек на то, что они действительно не знают, что делают. Существует множество библиотек валют/фиксированных точек для C++, и их легко написать самостоятельно. - person Aaron Digulla; 21.11.2011
comment
@Peter: это явно вопрос Java, а не C / C ++, и в Java BigDecimal - это класс, созданный специально для того, чтобы избежать неточностей двойных чисел и чисел с плавающей запятой. Ахсан правильно понял это, и, боюсь, совет ему не использовать десятичные типы не отвечает на его вопрос. Банки, использующие двойники, должны быть привлечены к ответственности ;-) - person Amos M. Carpenter; 21.11.2011
comment
Целые числа бесполезны при конвертации валют, особенно если учесть, что обменные курсы выражаются в десятичных дробях. - person Vineet Reynolds; 21.11.2011
comment
@aaamos, double в C/C++ не более точен, чем в Java, и все же C/C++ используется для финансовых приложений. Утверждение, что вы не можете использовать double в качестве денег, не соответствует тому, как это на самом деле используется в промышленности. - person Peter Lawrey; 21.11.2011
comment
@VineetReynolds, обменные курсы могут быть представлены в виде значений int с фиксированной точкой. Большинство высокочастотных торговых систем FX используют значения int или long. Я работал над парой и брал интервью у многих разработчиков в этой сфере. - person Peter Lawrey; 21.11.2011
comment
@Peter: Ни одно из двух финансовых учреждений, в которых я работал, не использовало C для конфиденциальных вычислений (одно использовало Java, одно — Smalltalk). Даже те, кто использует C, я уверен, что когда дело доходит до расчетов, в которых ставки указаны с точностью до 8 знаков после запятой и умножаются на миллионы долларов, они следят за тем, чтобы не использовать двойные числа, и надеются, что никто не заметит ошибки округления. (что было бы весьма существенно на этом уровне)... - person Amos M. Carpenter; 21.11.2011
comment
@Peter, если вам не нужно обрабатывать переполнение в результате, вы можете представлять обменные курсы в виде целых чисел или любого примитивного типа. Хотя это может быть верно для HFT, это не обязательно верно для всех систем учета и во всех сценариях. При работе с гиперинфляционными валютами (такими как доллар Зимбабве) BigDecimals — лучший/единственный выбор. - person Vineet Reynolds; 21.11.2011
comment
@VineetReynolds, это правда, однако большинство финансовых учреждений не работают с гиперинфляционными валютами. - person Peter Lawrey; 21.11.2011
comment
@ Питер, гиперинфляция - это всего лишь один пример, когда в результате можно увидеть переполнение. Расчет оборота и остатков по счетам нескольких крупных компаний, центральных банков и кредитных учреждений был бы еще одним местом, где использование примитивов привело бы к переполнению. - person Vineet Reynolds; 21.11.2011
comment
@VineetReynolds, даже в случае гиперинфляции деньги должны быть понятны как людям, так и компьютерам. Это накладывает верхний предел на самые большие числа, которые может иметь валюта, иначе никто не сможет их понять. В самых крайних случаях верхний предел близок к пределу long, и если вам нужно, например, представить 32 776 899 763 734 490 417,05 знаков, вам нужен BigDecimal. Однако, если вам нужно представить только государственный долг США (который в любом случае является лишь оценкой) или число меньше этого, вы можете использовать double или long. например 15 053 696 987 162,77 - person Peter Lawrey; 21.11.2011
comment
Иронично ли, что самая информативная часть этого обсуждения находится под ответом, за который проголосовали 5 раз? - person niken; 04.03.2014