在欧洲,小数用' , ' 分隔,我们使用可选' .'分开成千上万.我允许货币值:
我使用下一个正则表达式(来自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})?)$
Run Code Online (Sandbox Code Playgroud)
我想将货币字符串解析为浮点数.例如
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
}
Run Code Online (Sandbox Code Playgroud)
使用BigDecimal而不是Float
感谢大家的回答.我已将我的代码更改为使用BigDecimal而不是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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
Mic*_*tta 35
要回答一个稍微不同的问题:不要使用浮点类型来表示货币值. 它会咬你.使用base-10类型,比如BigDecimal或类似的整数类型int或long(表示您的值的量 - 例如,以美元计算的便士).
您将无法存储精确值 - 例如,123.45作为浮点数,并且对该值的数学运算(例如乘以税率)将产生舍入误差.
该页面的示例:
float a = 8250325.12f;
float b = 4321456.31f;
float c = a + b;
System.out.println(NumberFormat.getCurrencyInstance().format(c));
// prints $12,571,782.00 (wrong)
BigDecimal a1 = new BigDecimal("8250325.12");
BigDecimal b1 = new BigDecimal("4321456.31");
BigDecimal c1 = a1.add(b1);
System.out.println(NumberFormat.getCurrencyInstance().format(c1));
// prints $12,571,781.43 (right)
Run Code Online (Sandbox Code Playgroud)
在钱方面你不想犯错误.
关于最初的问题,我在一段时间内没有触及Java,但我知道我想远离正则表达式做这种工作.我看到这个推荐; 它可能会帮助你.未经测试; 警告开发者.
try {
String string = NumberFormat.getCurrencyInstance(Locale.GERMANY)
.format(123.45);
Number number = NumberFormat.getCurrencyInstance(locale)
.parse("$123.45");
// 123.45
if (number instanceof Long) {
// Long value
} else {
// too large for long - may want to handle as error
}
} catch (ParseException e) {
// handle
}
Run Code Online (Sandbox Code Playgroud)
查找具有与您期望看到的规则相匹配的规则的区域设置.如果找不到,请按顺序使用多个,或创建自己的自定义NumberFormat.
我还考虑强制用户以单一规范格式输入值.123.45和123.456的外观的方式太相似了,我的口味,并通过你的规则会导致通过的1000倍相差值 这是数以百万计是如何丢失的.