В Европе десятичные дроби разделяются с помощью ', ', и мы используем необязательный '. ' для разделения тысяч. Я разрешаю значения валют с:
- в стиле США 123 456,78
- европейский стиль 123.456,78 нотация
Я использую следующее регулярное выражение (из библиотеки RegexBuddy) для проверки ввода. Я допускаю необязательные двухзначные дроби и необязательные разделители тысяч.
^[+-]?[0-9]{1,3}(?:[0-9]*(?:[.,][0-9]{0,2})?|(?:,[0-9]{3})*(?:\.[0-9]{0,2})?|(?:\.[0-9]{3})*(?:,[0-9]{0,2})?)$
Я хотел бы проанализировать строку валюты с плавающей точкой. Например
123 456,78 следует сохранить как 123456,78
123,456,78 следует хранить как 123456,78
123,45 следует хранить как 123,45
1.234 следует хранить как 1234
12,34 следует хранить как 12,34
и так далее ...
Есть ли простой способ сделать это на Java?
public float currencyToFloat(String currency) {
// transform and return as float
}
Используйте BigDecimal вместо Float
Спасибо всем за отличные ответы. Я изменил свой код, чтобы использовать BigDecimal вместо float. Я оставлю предыдущую часть этого вопроса с помощью float, чтобы люди не делали те же ошибки, что и я.
Решение
Следующий код показывает функцию, которая преобразует валюту США и ЕС в строку, принятую конструктором BigDecimal (String). То есть это строка без разделителя тысяч и точка для дробей.
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class TestUSAndEUCurrency {
public static void main(String[] args) throws Exception {
test("123,456.78","123456.78");
test("123.456,78","123456.78");
test("123.45","123.45");
test("1.234","1234");
test("12","12");
test("12.1","12.1");
test("1.13","1.13");
test("1.1","1.1");
test("1,2","1.2");
test("1","1");
}
public static void test(String value, String expected_output) throws Exception {
String output = currencyToBigDecimalFormat(value);
if(!output.equals(expected_output)) {
System.out.println("ERROR expected: " + expected_output + " output " + output);
}
}
public static String currencyToBigDecimalFormat(String currency) throws Exception {
if(!doesMatch(currency,"^[+-]?[0-9]{1,3}(?:[0-9]*(?:[.,][0-9]{0,2})?|(?:,[0-9]{3})*(?:\\.[0-9]{0,2})?|(?:\\.[0-9]{3})*(?:,[0-9]{0,2})?)$"))
throw new Exception("Currency in wrong format " + currency);
// Replace all dots with commas
currency = currency.replaceAll("\\.", ",");
// If fractions exist, the separator must be a .
if(currency.length()>=3) {
char[] chars = currency.toCharArray();
if(chars[chars.length-2] == ',') {
chars[chars.length-2] = '.';
} else if(chars[chars.length-3] == ',') {
chars[chars.length-3] = '.';
}
currency = new String(chars);
}
// Remove all commas
return currency.replaceAll(",", "");
}
public static boolean doesMatch(String s, String pattern) {
try {
Pattern patt = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
Matcher matcher = patt.matcher(s);
return matcher.matches();
} catch (RuntimeException e) {
return false;
}
}
}