Конвертация валюты разных стран в 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);