Java将长整型转换为货币

19

我在将一个长整型数值(以分为单位)转换为货币格式时遇到了问题。

我的代码:

long doublePayment = 1099;  //Should equal $10.99
DecimalFormat dFormat = new DecimalFormat();
String formattedString = dFormat.format(doublePayment);
System.out.println(formattedString);

输出:1,099

我还尝试了:

long doublePayment = 1099;
NumberFormat n = NumberFormat.getCurrencyInstance(Locale.US); 
String s = n.format(doublePayment);
System.out.println(s);

因为这是美分,所以输出应该是10.99美元或$10.99。

我无法弄清楚我做错了什么。谢谢!!!


抱歉,我不知道为什么我的代码没有进入“CodeFormat”,提前道歉。 - mcd
因为你需要在代码之前换行;我已经帮你修复了。 - Jesper
2
你应该使用BigDecimal来处理货币:https://dev59.com/dnVC5IYBdhLWcg3wdw65 - wulfgarpro
我知道这可能有点老套,但还是值得一提的是,如果钱以分为单位发送,并且只是用于显示(就像用户所要求的那样),那么就不会有任何问题。只有在进行计算时才应使用BigDecimal。 - RED_
7个回答

39

如果您需要处理长数字,仍应使用java.math.BigDecimal。

    long doublePayment = 1099;
    BigDecimal payment = new BigDecimal(doublePayment).movePointLeft(2);
    System.out.println("$" + payment); // produces: $10.99

再次强调:不能使用浮点数变量来存储货币价值。


2
除了大多数投资银行使用“double”之外,C或C ++中没有BigDecimal,但许多系统仍然使用C或C ++。 ;) - Peter Lawrey
3
我认为银行会使用整数或长整数来存储分或分之一的金额,因为浮点运算可能会产生微小误差,而这种误差在银行系统中是不被允许的。 - Lauri
2
小错误不是随机错误。你可以预测它们可能有多大并使用适当的舍入。你说得对,long和int也被使用,但在我看来这些用得较少。如果你不知道如何使用适当的舍入,那么使用BigDecimal是正确的。 - Peter Lawrey
1
虽然我来晚了一点,但银行进行的测试比几乎任何人都多(我敢肯定他们只会被NASA、中央情报局和核电站之类的机构超过)——如果每个人都像银行那样测试他们的代码,他们就会发现防止使用浮点数的边缘情况。你典型的网络创业公司不会这样做,他们应该绝对使用大十进制。 (我知道有一家公司使用浮点数处理了数亿美元的交易,直到一个客户发现了一个差一分钱的报告,然后就开始疑惑了?花了六个月才修复!!) - corsiKa

28

如果要将美分转换为美元,您可以使用以下方法

long doublePayment = 1099;
NumberFormat n = NumberFormat.getCurrencyInstance(Locale.US); 
String s = n.format(doublePayment / 100.0);
System.out.println(s);

这将精确到70万亿。


我之前尝试过我认为是这样的,但是我写成了"x / 100",甚至没有意识到这与"x / 100.0"不同。 - mcd
1
是的,一个整数除以一个整数会得到一个整数。实际上应该得到一个双精度浮点数,你可以将其转换为整数进行整数除法,但你需要至少有一个双精度浮点数/整数或整数/双精度浮点数才能得到一个双精度浮点数。 - Peter Lawrey

10
你的字面值是1099,也就是一千零九十九,符合Java整数字面值规则。根据你的JVM语言环境,这个数字会用1,099表示。如果你在欧洲,它将变成1.099。因此,这不是你的输出问题,而是你的输入问题。
问题在于你需要表示一个定点值,但你不了解java.math.BigDecimal,试图伪造它。当你进行一些计算时,会出现问题。不要这样做。
这就是你应该做的。简单地说(代码也少得多):
BigDecimal payment = new BigDecimal("10.99");
System.out.println(String.format("$%.2f", payment));

注意如何使用字符串来初始化数字。此外,String.format()会处理当前语言环境,或者您可以通过重载的方法提供所需的语言环境。

3
可能情况是,David 持有以分为单位的长整型数值,那么他应该使用新的 BigDecimal(doublePayment).movePointLeft(2) 方法。 - Lauri

7

这些答案都没有考虑不同地区的货币具有不同数量的小数位。例如,日元没有小数位,而约旦第纳尔有三个小数位,当然,美元有两个小数位。我认为这是更合适的解决方案:

    long payment = 1099L;
    BigDecimal bd = new BigDecimal(payment);

    Locale jpLocale = new Locale("ja", "JP");//Japan

    Currency jpCurrency = Currency.getInstance(jpLocale);
    NumberFormat jpnf = NumberFormat.getCurrencyInstance(jpLocale);
    int jpNumFractionalDigits = jpCurrency.getDefaultFractionDigits();

    BigDecimal jpbd = bd.movePointLeft(jpNumFractionalDigits);


    Locale usLocale = new Locale("en", "US");//United States

    Currency usCurrency = Currency.getInstance(usLocale);
    NumberFormat usnf = NumberFormat.getCurrencyInstance(usLocale);
    int usNumFractionalDigits = usCurrency.getDefaultFractionDigits();

    BigDecimal usbd = bd.movePointLeft(usNumFractionalDigits);



    System.out.println(jpnf.format(jpbd)); //prints ¥1,099
    System.out.println(usnf.format(usbd));//prints $10.99

此外,还存在更多奇怪的货币系统。例如,1971年之前的英镑。1英镑 = 20先令,1先令 = 12便士,因此1英镑 = 240便士。并且他们还有半便士和四分之一便士。http://projectbritain.com/moneyold.htm - Lauri
非常感谢你,这正是我正在寻找的!谢谢并点赞! - Jeff

2

这并不是格式问题,而是输入问题。将您的输入除以100,就可以解决问题。

float payment = 1099 / ((float) 100);

1
我会使用double而不是float,因为表示误差会更小。例如:double payment = 1099 / 100.0; - Peter Lawrey

0

double doublePayment = 10.99; 您需要像这样提供货币。 NumberFormat 不会理解您是以美分还是美元提供它,除非它看到小数点。


0

使用货币格式化程序:

NumberFormat nf = NumberFormat.getCurrencyInstance(Locale.ENGLISH);
String output = nf.format(value);
System.out.println(value + " " + output);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接