我试图使用多头为货币创建自己的类,但显然我应该使用 BigDecimal 反而。有人可以帮助我开始吗?最好的使用方法是什么 BigDecimal美元货币,例如美分至少但不超过小数点后两位,等等。该API用于 BigDecimal 太大了,不知道用什么方法。还, BigDecimal 具有更好的精度,但是如果它通过一个 double?如果我做新的 BigDecimal(24.99), ,它与使用 a 有什么不同 double?或者我应该使用使用 a 的构造函数 String 反而?

有帮助吗?

解决方案

以下是一些提示:

  1. 使用 BigDecimal 如果您需要它提供的精度(货币价值通常需要这个),则可以用于计算。
  2. 使用 NumberFormat 用于显示的类。此类将处理不同货币金额的本地化问题。然而,它只会接受原语;因此,如果您可以接受由于转换为 double, ,你可以使用这个类。
  3. 当使用 NumberFormat 类,使用 scale() 方法上的 BigDecimal 实例设置精度和舍入方法。

附:如果您想知道, BigDecimal 总是比 double, ,当你必须用 Java 表示货币价值时.

聚苯醚:

创造 BigDecimal 实例

这相当简单,因为 BigDecimal 提供构造函数来获取原始值, , 和 String 对象。你可以使用那些, 最好是采取 String 目的. 。例如,

BigDecimal modelVal = new BigDecimal("24.455");
BigDecimal displayVal = modelVal.setScale(2, RoundingMode.HALF_EVEN);

显示中 BigDecimal 实例

你可以使用 setMinimumFractionDigitssetMaximumFractionDigits 方法调用以限制显示的数据量。

NumberFormat usdCostFormat = NumberFormat.getCurrencyInstance(Locale.US);
usdCostFormat.setMinimumFractionDigits( 1 );
usdCostFormat.setMaximumFractionDigits( 2 );
System.out.println( usdCostFormat.format(displayVal.doubleValue()) );

其他提示

我会建议对货币格局有一点研究。 Martin Fowler的在他的书中分析模式更详细地涵盖了这一点。

public class Money {

    private static final Currency USD = Currency.getInstance("USD");
    private static final RoundingMode DEFAULT_ROUNDING = RoundingMode.HALF_EVEN;

    private final BigDecimal amount;
    private final Currency currency;   

    public static Money dollars(BigDecimal amount) {
        return new Money(amount, USD);
    }

    Money(BigDecimal amount, Currency currency) {
        this(amount, currency, DEFAULT_ROUNDING);
    }

    Money(BigDecimal amount, Currency currency, RoundingMode rounding) {
        this.currency = currency;      
        this.amount = amount.setScale(currency.getDefaultFractionDigits(), rounding);
    }

    public BigDecimal getAmount() {
        return amount;
    }

    public Currency getCurrency() {
        return currency;
    }

    @Override
    public String toString() {
        return getCurrency().getSymbol() + " " + getAmount();
    }

    public String toString(Locale locale) {
        return getCurrency().getSymbol(locale) + " " + getAmount();
    }   
}

来到的用法:

您将代表使用Money对象相对于BigDecimal所有款项。代表钱大小数将意味着你将有你在那里显示它的每一个格式化的钱。试想一下,如果显示标准的变化。你将不得不进行编辑所有的地方。代替使用Money图案你集中的钱格式化到单个位置。

Money price = Money.dollars(38.28);
System.out.println(price);

或者,等待 JSR-354 。 Java的货币和货币API即将推出!

1)如果要限定于double精度,一个理由使用BigDecimals是实现与来自BigDecimals创建的doubles操作。

2)BigDecimal包括一个任意精度的整数非标度值和一个非负的32位整数的规模,而双包装在一个对象的原始类型double的值。型Double的一个对象包含单个字段其类型double

3)它应该没有什么区别

您应该与$和精度没有任何困难。它是使用System.out.printf一种方式做

当你想四舍五入到小数点后2分分钱用BigDecimal.setScale(2, BigDecimal.ROUND_HALF_UP)。要知道,当你做计算,虽然舍入误差。你需要是一致的,当你会做物有所值的舍入。无论是做四舍五入就在刚刚结束一次所有的计算都完成后,或做任何计算之前使用四舍五入到每个值。使用哪一个将取决于您的业务需求,但通常,我觉得做四舍五入就在年底似乎做出更好的感觉给我。

当你构建Stringde物有所值使用BigDecimal。如果你使用double,它会在最后一个尾随浮点值。这是由于计算机体系结构有关double / float值是如何用二进制格式表示。

原始数字类型是用于在存储器中存储单个值是有用的。但是,使用双和float类型的计算处理时,没有与rounding.It一个问题是因为内存中表示不完全映射到值。例如,双值应该采取64位,但Java没有使用全部64个bits.It只保存它认为数的重要组成部分。所以,你可以在你的float或double类型的值加在一起,得出了错误的价值观。

请看到短片 https://youtu.be/EXxUSz9x7BM

有是如何做到这一点上javapractices.com广泛例子。具体见 Money 类,这是为了使货币计算不是直接使用BigDecimal简单。

Money类的设计是为了使表达更自然。例如:

if ( amount.lt(hundred) ) {
 cost = amount.times(price); 
}

在WEB4J工具具有类似类,称为 Decimal ,这是一个位比Money类更抛光。

NumberFormat.getNumberInstance(java.util.Locale.US).format(num);

<强>我将基团。没有的BigDecimal。

下面是一个伟大的文章 https://lemnik.wordpress.com/2011/03 / 25 / BigDecimal的,和你的钱/

思想从这里开始。

import java.math.BigDecimal;

public class Main {

    public static void main(String[] args) {
        testConstructors();
        testEqualsAndCompare();
        testArithmetic();
    }

    private static void testEqualsAndCompare() {
        final BigDecimal zero = new BigDecimal("0.0");
        final BigDecimal zerozero = new BigDecimal("0.00");

        boolean zerosAreEqual = zero.equals(zerozero);
        boolean zerosAreEqual2 = zerozero.equals(zero);

        System.out.println("zerosAreEqual: " + zerosAreEqual + " " + zerosAreEqual2);

        int zerosCompare = zero.compareTo(zerozero);
        int zerosCompare2 = zerozero.compareTo(zero);
        System.out.println("zerosCompare: " + zerosCompare + " " + zerosCompare2);
    }

    private static void testArithmetic() {
        try {
            BigDecimal value = new BigDecimal(1);
            value = value.divide(new BigDecimal(3));
            System.out.println(value);
        } catch (ArithmeticException e) {
            System.out.println("Failed to devide. " + e.getMessage());
        }
    }

    private static void testConstructors() {
        double doubleValue = 35.7;
        BigDecimal fromDouble = new BigDecimal(doubleValue);
        BigDecimal fromString = new BigDecimal("35.7");

        boolean decimalsEqual = fromDouble.equals(fromString);
        boolean decimalsEqual2 = fromString.equals(fromDouble);

        System.out.println("From double: " + fromDouble);
        System.out.println("decimalsEqual: " + decimalsEqual + " " + decimalsEqual2);
    }
}

它打印

From double: 35.7000000000000028421709430404007434844970703125
decimalsEqual: false false
zerosAreEqual: false false
zerosCompare: 0 0
Failed to devide. Non-terminating decimal expansion; no exact representable decimal result.

如何存储的BigDecimal到数据库中?地狱,它也存储为一个double值???至少,如果我使用的MongoDB没有任何高级配置它将BigDecimal.TEN存储为1E1

可能的解决方案?

我一个人来 - 用String在Java中存储的BigDecimal为字符串到数据库中。您可以验证,例如@NotNull@Min(10)等..然后你就可以使用触发器在更新或保存检查,如果当前字符串是一个数字,你需要的。有没有触发器,蒙戈虽然。 有MongoDB的触发内置方式函数调用?

有是我身边有乐趣的一个缺点 - 的BigDecimal作为字符串在扬鞭defenition

我需要生成招摇,所以我们前端的团队明白,我通过他们由字符串的数字。的日期时间作为示例呈现为一个字符串。

有另一种凉溶液I上述文章中读... 使用以存储精确的数字。

  

有一个标准的长值可以存储团结状态国债的当前值(如美分,不计)6477次无任何溢出。什么是更多:它是一个整数类型,而不是一个浮点。这使得它更容易和准确的工作,并保证行为。


更新

https://stackoverflow.com/a/27978223/4587961

也许在未来的MongoDB将增加对BigDecimal的支持。 https://jira.mongodb.org/browse/SERVER-1393 3.3.8似乎已经完成这件事。

有第二种方法的一个例子。采用定标。 HTTP: //www.technology-ebay.de/the-teams/mobile-de/blog/mapping-bigdecimals-with-morphia-for-mongodb.html

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top