В Европе десятичные знаки разделяются ",", и мы используем необязательные "." для разделения тысяч. Я допускаю валютные значения с помощью:
- Обозначение в США 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})?)$
Я хотел бы проанализировать строку валюты для float. Например
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;
}
}
}