使用java将不同国家的货币转换为双倍

2022-09-04 07:01:37

我曾经有过一个场景,其中我以字符串的形式获取货币,例如:

$199.00

R$ 399,00

£25.00

90,83 €

迪拉姆 449.00

如何在Java中将这些货币转换为双倍?


答案 1

切勿使用双精度来表示确切的金额

好吧,你当然可以做到,但你需要真正理解浮点算术

使用 .虽然它确实处理一些货币,但通常更容易剥离所有货币符号。将用于计算要使用的分隔符:NumberFormatNumberFormatLocale

public static BigDecimal parse(final String amount, final Locale locale) throws ParseException {
    final NumberFormat format = NumberFormat.getNumberInstance(locale);
    if (format instanceof DecimalFormat) {
        ((DecimalFormat) format).setParseBigDecimal(true);
    }
    return (BigDecimal) format.parse(amount.replaceAll("[^\\d.,]",""));
}

这需要 a 的量和 .然后,它会创建一个解析实例。它使用 和 regex 去除除数字之外的所有数字,然后从数字中解析它。StringLocaleBigDecimalNumberFormatreplaceAll.,

针对您的示例的快速演示:

public static void main(String[] args) throws ParseException {
    final String dollarsA = "$199.00";
    final String real = "R$ 399,00";
    final String dollarsB = "£25.00";
    final String tailingEuro = "90,83 €";
    final String dollarsC = "$199.00";
    final String dirham = "AED 449.00";

    System.out.println(parse(dollarsA, Locale.US));
    System.out.println(parse(real, Locale.FRANCE));
    System.out.println(parse(dollarsB, Locale.US));
    System.out.println(parse(tailingEuro, Locale.FRANCE));
    System.out.println(parse(dollarsC, Locale.US));
    System.out.println(parse(dirham, Locale.US));
}

输出:

199.00
399.00
25.00
90.83
199.00
449.00

我只是简单地使用了小数点的位置和小数点的位置,但是如果您愿意,可以使用正确的货币。US.FRANCE,Locale


答案 2

正如大卫·华莱士(David Wallace)所说,你不会(或者如果你这样做,你这样做会非常小心,只有在深入了解这些问题的情况下才会这样做),因为通常不适合与货币价值一起使用。它有诸如最终存在(以及其他类似)之类的问题。正确使用的BigDecimal可能更适合,尽管速度要慢得多。(下面有关“正确使用”的更多信息。double0.1 + 0.20.30000000000000004

首先,您必须从区域设置中确定所使用的千位和小数点分隔符是什么(请参阅Boris的出色答案以获取更多信息),或者通过随字符串一起提供该信息来确定。在某些文化中,它们是(千)和(十进制),例如“1,000.24”,但在其他文化中则相反(例如,“1.000,24”)。据我所知,在某些地方还使用了其他字符。(你无法从字符串中猜到这一点,你不知道是意味着一千二百三十四还是一点二三四。,."1,234"

一旦知道它们是什么,就要删除千位分隔符,将小数转换为(特别是),然后从字符串中删除所有非数字,非减号,非小数:.

// where `currencyString` is the string containing the currency
currencyString = currencyString
                     .replace(thousandsString, "")
                     .replace(decimalString, ".")
                     .replaceAll("[^\\d.-]", "");

然后构造您的 :BigDecimal

BigDecimal currency = new BigDecimal(currencyString);

...并设置适合您的程序的缩放和舍入模式。另外,请务必仔细阅读Javadoc以获取各种操作方法。例如,正如 Peter Lawrey 在注释中指出的那样,天真地使用 会给你带来运行时异常:BigDecimal

BigDecimal bd = new BigDecimal(43);
bd = bd.divide(new BigDecimal(7)); // Throws ArithmeticException

您可以通过提供舍入信息来处理这些情况:

BigDecimal bd = new BigDecimal(43);
bd = bd.divide(new BigDecimal(7), RoundingMode.HALF_UP);

...但同样,请务必设置适合您正在做的事情的规模。例如,如果您的刻度仅为 ,则 with 将代替 。除法特别棘手,您可能需要大幅的比例,然后最终舍入回更正常的货币水平等级(通常为2,但有时您可能想要更多的地方)。2(43 / 7) * 7RoundingMode.HALF_UP42.9843


如果你真的,真的,真的想要一个,使用Double.parseDoubledouble

// where `currencyString` is the string containing the currency
currencyString = currencyString
                     .replace(thousandsString, "")
                     .replace(decimalString, ".")
                     .replaceAll("[^\\d.-]", "");
double thisWillHaveIssues = Double.parseDouble(currencyString);