Чтобы получить лучший ответ, вы должны сообщить нам, чего вы хотите достичь.
Тем не менее, BigDecimal является правильным типом для использования в Java, потому что он может сохранять любую точность, а также позволяет вам выбрать режим округления, наиболее подходящий для вашего случая.
В большинстве случаев BigDecimal является единственным допустимым выбором для валют. Но выбор стратегии округления не столь очевиден.
По умолчанию используется HALF_EVEN, что происходит с быть хорошим выбором. Этот алгоритм известен как банковское округление (см. обсуждение здесь).
Другой распространенной стратегией является HALF_UP. более интуитивно понятен, но имеет несколько худшие статистические характеристики.
Также обратите внимание, что во многих случаях (особенно в банковском деле и страховании) стратегия округления будет диктоваться бизнес-требованиями, часто разными для разных вариантов использования.
personTomasz Nurkiewiczschedule21.11.2011
comment
Вы должны добавить, что HALF_EVEN неэффективен.
- personJus12; 14.11.2017
Обычно вы используете округление «половина вверх», например:
myBigDecimal.setScale(2, RoundingMode.HALF_UP);
Таким образом, вы будете округлять до двух знаков после запятой (которые используются в большинстве валют, например, доллары и центы, очевидно, есть исключения), и вы будете округлять значения так, что полцента или больше будут округляться, а менее половины цента будет округляться вниз. Дополнительные сведения см. в документе по Java. Детали.
Для финансовых приложений ROUND_HALF_EVEN является наиболее распространенным режимом округления. Этот режим позволяет избежать предвзятости. Но для отображения вы должны использовать класс NumberFormat. Этот класс позаботится о локализации сумм в разных валютах. Но NumberFormat принимает только примитивы. Поэтому используйте последний, если вы можете принять небольшое изменение точности при преобразованиях в двойное.
Вы никогда не должны использовать десятичный тип для валют. Используйте целочисленный тип. Это поддерживает точность, избегая ошибок округления, связанных с числами с плавающей запятой.
При отображении суммы разделите ее на соответствующий коэффициент, чтобы получить нецелую часть.
personBrett Walkerschedule21.11.2011
comment
На самом деле, BigDecimals совершенно безопасны и точны при правильном использовании. Только не используйте double или float.
- personAmos M. Carpenter; 21.11.2011
comment
+1: @aaamos, за исключением того, что большинство инвестиционных банков используют double, иногда int/long. особенно тех, кто использует C/C++, у него нет встроенного десятичного типа.
- personPeter Lawrey; 21.11.2011
comment
@Peter: еще один намек на то, что они действительно не знают, что делают. Существует множество библиотек валют/фиксированных точек для C++, и их легко написать самостоятельно.
- personAaron Digulla; 21.11.2011
comment
@Peter: это явно вопрос Java, а не C / C ++, и в Java BigDecimal - это класс, созданный специально для того, чтобы избежать неточностей двойных чисел и чисел с плавающей запятой. Ахсан правильно понял это, и, боюсь, совет ему не использовать десятичные типы не отвечает на его вопрос. Банки, использующие двойники, должны быть привлечены к ответственности ;-)
- personAmos M. Carpenter; 21.11.2011
comment
Целые числа бесполезны при конвертации валют, особенно если учесть, что обменные курсы выражаются в десятичных дробях.
- personVineet Reynolds; 21.11.2011
comment
@aaamos, double в C/C++ не более точен, чем в Java, и все же C/C++ используется для финансовых приложений. Утверждение, что вы не можете использовать double в качестве денег, не соответствует тому, как это на самом деле используется в промышленности.
- personPeter Lawrey; 21.11.2011
comment
@VineetReynolds, обменные курсы могут быть представлены в виде значений int с фиксированной точкой. Большинство высокочастотных торговых систем FX используют значения int или long. Я работал над парой и брал интервью у многих разработчиков в этой сфере.
- personPeter Lawrey; 21.11.2011
comment
@Peter: Ни одно из двух финансовых учреждений, в которых я работал, не использовало C для конфиденциальных вычислений (одно использовало Java, одно — Smalltalk). Даже те, кто использует C, я уверен, что когда дело доходит до расчетов, в которых ставки указаны с точностью до 8 знаков после запятой и умножаются на миллионы долларов, они следят за тем, чтобы не использовать двойные числа, и надеются, что никто не заметит ошибки округления. (что было бы весьма существенно на этом уровне)...
- personAmos M. Carpenter; 21.11.2011
comment
@Peter, если вам не нужно обрабатывать переполнение в результате, вы можете представлять обменные курсы в виде целых чисел или любого примитивного типа. Хотя это может быть верно для HFT, это не обязательно верно для всех систем учета и во всех сценариях. При работе с гиперинфляционными валютами (такими как доллар Зимбабве) BigDecimals — лучший/единственный выбор.
- personVineet Reynolds; 21.11.2011
comment
@VineetReynolds, это правда, однако большинство финансовых учреждений не работают с гиперинфляционными валютами.
- personPeter Lawrey; 21.11.2011
comment
@ Питер, гиперинфляция - это всего лишь один пример, когда в результате можно увидеть переполнение. Расчет оборота и остатков по счетам нескольких крупных компаний, центральных банков и кредитных учреждений был бы еще одним местом, где использование примитивов привело бы к переполнению.
- personVineet Reynolds; 21.11.2011
comment
@VineetReynolds, даже в случае гиперинфляции деньги должны быть понятны как людям, так и компьютерам. Это накладывает верхний предел на самые большие числа, которые может иметь валюта, иначе никто не сможет их понять. В самых крайних случаях верхний предел близок к пределу long, и если вам нужно, например, представить 32 776 899 763 734 490 417,05 знаков, вам нужен BigDecimal. Однако, если вам нужно представить только государственный долг США (который в любом случае является лишь оценкой) или число меньше этого, вы можете использовать double или long. например 15 053 696 987 162,77
- personPeter Lawrey; 21.11.2011
comment
Иронично ли, что самая информативная часть этого обсуждения находится под ответом, за который проголосовали 5 раз?
- personniken; 04.03.2014