gpt4 book ai didi

java - 如何将货币金额(美国或欧盟)解析为 Java 中的浮点值

转载 作者:搜寻专家 更新时间:2023-10-30 20:56:42 25 4
gpt4 key购买 nike

在欧洲,小数点用“,”分隔,我们使用可选的“.”来分隔千位。我允许以下货币值:

  • 美式 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 应存储为 123412.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;
}
}

}

最佳答案

回答一个稍微不同的问题:不要使用浮点类型来表示货币值。 It will bite you。请改用以 10 为基数的类型,例如 BigDecimal,或整数类型,例如 intlong(代表您的值的数量 - 便士,例如,以美元计算)。

您将无法存储精确值 - 例如 123.45,作为 float ,对该值的数学运算(例如乘以税率)会产生舍入误差。

该页面的示例:

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)

在涉及金钱时,您不想犯错误。

关于最初的问题,我有一段时间没有接触 Java,但我知道我想远离 regex 来做这种工作。我看到这个推荐;它可能对你有帮助。未经测试;警告开发者。

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
}

寻找规则符合您期望看到的区域设置。如果找不到,请按顺序使用多个,或创建您自己的 custom NumberFormat

我还会考虑强制用户以单一的规范格式输入值。 123.45 和 123.456 看起来方式对我来说太相似了,按照你的规则会导致值相差 1000 倍。This is how millions are lost

关于java - 如何将货币金额(美国或欧盟)解析为 Java 中的浮点值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/965831/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com