【发布时间】:2010-11-01 05:42:26
【问题描述】:
在欧洲,小数点用“,”分隔,我们使用可选的“.”分隔千位。我允许使用以下货币值:
- 美式 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。我会将这个问题的前一部分保留为浮动,以防止人们犯我会犯的同样错误。
解决方案
下一个代码显示了一个函数,该函数将美国和欧盟货币转换为 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;
}
}
}
【问题讨论】:
-
那么 1.23 转换成什么?你的规则集是矛盾的。为什么不利用应用程序客户端的本地化功能?
-
好吧,我的错……但说真的,在不知道它来自的语言环境的情况下试图破译它有一股难闻的气味。
-
嗯,基本上我最感兴趣的是解决欧盟符号样式的问题。但是最好有一个标准的解决方案。
-
@sergio:更新了我的答案。尝试现有的特定于语言环境的 NumberFormats,或使用您期望的格式创建一个自定义的。