Конвертация валюты разных стран в double с помощью java

У меня есть один раз сценарий, где я получаю валюты в виде строки, например:

199.00$

R$ 399,00

£25.00

€90,83

AED 449.00

Как конвертировать эти валюты в double на java?

4 ответов


никогда не используйте double для представления точных сумм

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

использовать NumberFormat. Пока он справляется некоторые валюты, обычно проще просто удалить все символы валюты. The NumberFormat использовать Locale отработать разделители:

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.,]",""));
}

это String суммы и Locale. Затем он создает BigDecimal извлечение NumberFormat экземпляра. Он использует replaceAll и regex, чтобы удалить все, кроме цифр,. и , из числа затем анализирует его.

быстрая демонстрация против ваших примеров:

public static void main(String[] args) throws ParseException {
    final String dollarsA = "9.00";
    final String real = "R$ 399,00";
    final String dollarsB = "£25.00";
    final String tailingEuro = "90,83 €";
    final String dollarsC = "9.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 для валюты, если хотите.


как сказал Дэвид Уоллес ,Вы не делаете (или если вы делаете, вы делаете это очень внимательно и только если глубоко информированы о проблемах), потому что double обычно не подходит для использования с валютными значениями. У него есть такие проблемы, как 0.1 + 0.2 становится 0.30000000000000004 (и других подобных). BigDecimal используется должным образом вероятно, лучше подходит, хотя и значительно медленнее. (Подробнее о "используется должным образом" ниже.)

во-первых, вы должны определить, что используются тысячи и десятичные разделители из локали (см. отличный ответ Бориса для большего об этом) или имея эту информацию, предоставленную вместе со строкой. В некоторых культурах, они , (тысячи) и . (десятичное число), например " 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 тщательно для различных методов работы. Например, как указал Питер Лоури в комментариях, наивное использование 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);

...но опять же, не забудьте установить шкалу, соответствующую тому, что вы делаете. Например, если ваш масштаб только 2, потом (43 / 7) * 7 С RoundingMode.HALF_UP будет 42.98 вместо 43. Деления особенно сложно, вам может понадобиться значительная шкала, а затем окончательное округление до более нормальных шкал валютного уровня (обычно 2, но иногда вам может понадобиться больше мест справа).


если вы действительно, действительно, действительно хотите double используйте Double.parseDouble:

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

использование содержит, заменяет и valueOf

if(line.constains("$")){
     double value=Double.valueOf(line.replace("$",""));
}
if(line.constains("£")){
     double value=Double.valueOf(line.replace("£",""));
}
//same with others

более простой способ - использовать DecimalFormal, как в следующем примере:

String myMoney = 90,83 €

String s

try {
s = DecimalFormat.getCurrencyInstance(Locale.getDefault()).parse (myMoney).toString()
} catch (ParseException e) {
return;
}

double d  = Double.parseDouble(s);