【问题标题】:How to format decimals in a currency format?Java 货币数字格式
【发布时间】:2011-01-23 16:00:35
【问题描述】:

有没有办法将小数格式化如下:

100   -> "100"  
100.1 -> "100.10"

如果是整数,则省略小数部分。否则格式为两位小数。

【问题讨论】:

    标签: java currency number-formatting


    【解决方案1】:

    是的。您可以使用java.util.formatter。您可以使用像“%10.2f”这样的格式化字符串

    【讨论】:

    • String.format() 是一个很好的静态包装器。不过,不确定您为什么使用“10”。
    • 由于没有关于数字大小的指导,我选择了 10 Ex Recto。我们不知道这是糖果的价格还是汽车的价格。我相信您也可以只执行 "%.2f" 以使总大小不受限制。
    • DD 希望省略小数部分,如果金额是货币单位的整数。
    【解决方案2】:

    你应该这样做:

    public static void main(String[] args) {
        double d1 = 100d;
        double d2 = 100.1d;
        print(d1);
        print(d2);
    }
    
    private static void print(double d) {
        String s = null;
        if (Math.round(d) != d) {
            s = String.format("%.2f", d);
        } else {
            s = String.format("%.0f", d);
        }
        System.out.println(s);
    }
    

    哪个打印:

    100

    100,10

    【讨论】:

    • Math.round(d) != d 会起作用吗?经常使用浮动!= 即使您认为是这样。
    • 另一种方式,如果 d 是 100.000000000000001 那么它仍然会打印为 100
    【解决方案3】:

    我对此表示怀疑。问题是如果它是一个浮点数,100 永远不会是 100,它通常是 99.9999999999 或 100.0000001 或类似的东西。

    如果您确实想这样格式化,则必须定义一个 epsilon,即与整数的最大距离,如果差异较小,则使用整数格式化,否则使用浮点数。

    这样的事情可以解决问题:

    public String formatDecimal(float number) {
      float epsilon = 0.004f; // 4 tenths of a cent
      if (Math.abs(Math.round(number) - number) < epsilon) {
         return String.format("%10.0f", number); // sdb
      } else {
         return String.format("%10.2f", number); // dj_segfault
      }
    }
    

    【讨论】:

    • 次要吹毛求疵:浮点数可以正好为 100,位模式为 0x42c80000。
    • 是的,正如 Karol S 所说,许多数字可以与浮点数完全匹配。只是不是所有的数字。 100 是一个可以表示的数字,你应该只考虑不能表示的数字。
    【解决方案4】:

    我建议使用 java.text 包:

    double money = 100.1;
    NumberFormat formatter = NumberFormat.getCurrencyInstance();
    String moneyString = formatter.format(money);
    System.out.println(moneyString);
    

    这具有特定于区域设置的额外好处。

    但是,如果必须的话,截断返回的字符串(如果它是一整美元):

    if (moneyString.endsWith(".00")) {
        int centsIndex = moneyString.lastIndexOf(".00");
        if (centsIndex != -1) {
            moneyString = moneyString.substring(1, centsIndex);
        }
    }
    

    【讨论】:

    • 您永远不应该使用双精度来表示货币。要么转换为长整数并自己管理小数点,要么将BigDecimal 与格式化程序一起使用。 joda-money.sourceforge.net 应该是一个很好的库,一旦完成就可以使用。
    • 我同意 re: double != money,但这不是问题的提出方式。
    • 货币的运作方式是什么意思?我可以说一些东西的成本是 1 美元而不是 1.00 美元......有不同的显示货币的方式(默认值除外),这个问题询问如果它是一个整数,如何省略小数部分。
    • 这是一个渲染问题。将逻辑放入您的 UI 以接受货币作为字符串并截断小数点和美分(如果它是精确的美元)。
    • 同意——这就是我在 5.5 年前写这篇文章时推荐使用 Locale 的原因。 “但是,如果你必须……”是关键词。
    【解决方案5】:

    谷歌搜索后我没有找到任何好的解决方案,只是发布我的解决方案以供其他人参考。使用 priceToString 格式化货币。

    public static String priceWithDecimal (Double price) {
        DecimalFormat formatter = new DecimalFormat("###,###,###.00");
        return formatter.format(price);
    }
    
    public static String priceWithoutDecimal (Double price) {
        DecimalFormat formatter = new DecimalFormat("###,###,###.##");
        return formatter.format(price);
    }
    
    public static String priceToString(Double price) {
        String toShow = priceWithoutDecimal(price);
        if (toShow.indexOf(".") > 0) {
            return priceWithDecimal(price);
        } else {
            return priceWithoutDecimal(price);
        }
    }
    

    【讨论】:

    • 他从来没有说过它更好。他刚刚发布了他的解决方案,以便其他人可以参考。至少你可以说是谢谢。
    • 如果我想以印度格式显示价格怎么办。没有小数。格式 --> ##,##,###
    • 在 priceWithDecimal(Double) 方法中,尝试将掩码 "###,###,###.00" 更改为 "###,###,##0.00" 以在值为“0”时显示“0,00”
    • 反之亦然将格式化的货币再次转换为 Double
    【解决方案6】:

    如果你想处理货币,你必须使用 BigDecimal 类。问题是,无法在内存中存储一​​些浮点数(例如,您可以存储 5.3456,但不能存储 5.3455),这会影响计算错误。

    有一篇很好的文章如何与BigDecimal和货币合作:

    http://www.javaworld.com/javaworld/jw-06-2001/jw-0601-cents.html

    【讨论】:

    • 这与我提出的问题完全无关。
    【解决方案7】:

    这就是我所做的,使用整数将金额表示为美分:

    public static String format(int moneyInCents) {
        String format;
        Number value;
        if (moneyInCents % 100 == 0) {
            format = "%d";
            value = moneyInCents / 100;
        } else {
            format = "%.2f";
            value = moneyInCents / 100.0;
        }
        return String.format(Locale.US, format, value);
    }
    

    NumberFormat.getCurrencyInstance() 的问题在于,有时你真的希望 20 美元变成 20 美元,但它看起来比 20.00 美元要好。

    如果有人找到更好的方法,使用 NumberFormat,我会全力以赴。

    【讨论】:

      【解决方案8】:

      我正在使用这个(使用来自 commons-lang 的 StringUtils):

      Double qty = 1.01;
      String res = String.format(Locale.GERMANY, "%.2f", qty);
      String fmt = StringUtils.removeEnd(res, ",00");
      

      您必须只处理语言环境和相应的要切碎的字符串。

      【讨论】:

        【解决方案9】:

        格式从 1000000.2 到 1 000 000,20

        private static final DecimalFormat DF = new DecimalFormat();
        
        public static String toCurrency(Double d) {
            if (d == null || "".equals(d) || "NaN".equals(d)) {
                return " - ";
            }
            BigDecimal bd = new BigDecimal(d);
            bd = bd.setScale(2, BigDecimal.ROUND_HALF_UP);
            DecimalFormatSymbols symbols = DF.getDecimalFormatSymbols();
            symbols.setGroupingSeparator(' ');
            String ret = DF.format(bd) + "";
            if (ret.indexOf(",") == -1) {
                ret += ",00";
            }
            if (ret.split(",")[1].length() != 2) {
                ret += "0";
            }
            return ret;
        }
        

        【讨论】:

          【解决方案10】:

          我知道这是一个老问题,但是......

          import java.text.*;
          
          public class FormatCurrency
          {
              public static void main(String[] args)
              {
                  double price = 123.4567;
                  DecimalFormat df = new DecimalFormat("#.##");
                  System.out.print(df.format(price));
              }
          }
          

          【讨论】:

          【解决方案11】:

          你可以做这样的事情,然后传入整数,然后传入美分。

          String.format("$%,d.%02d",wholeNum,change);
          

          【讨论】:

            【解决方案12】:

            这篇文章真的帮助我最终得到了我想要的东西。所以我只是想在这里贡献我的代码来帮助别人。这是我的代码和一些解释。

            以下代码:

            double moneyWithDecimals = 5.50;
            double moneyNoDecimals = 5.00;
            System.out.println(jeroensFormat(moneyWithDecimals));
            System.out.println(jeroensFormat(moneyNoDecimals));
            

            将返回:

            € 5,-
            € 5,50
            

            实际的 jeroensFormat() 方法:

            public String jeroensFormat(double money)//Wants to receive value of type double
            {
                    NumberFormat dutchFormat = NumberFormat.getCurrencyInstance();
                    money = money;
                    String twoDecimals = dutchFormat.format(money); //Format to string
                    if(tweeDecimalen.matches(".*[.]...[,]00$")){
                        String zeroDecimals = twoDecimals.substring(0, twoDecimals.length() -3);
                            return zeroDecimals;
                    }
                    if(twoDecimals.endsWith(",00")){
                        String zeroDecimals = String.format("€ %.0f,-", money);
                        return zeroDecimals; //Return with ,00 replaced to ,-
                    }
                    else{ //If endsWith != ,00 the actual twoDecimals string can be returned
                        return twoDecimals;
                    }
            }
            

            调用方法jeroensFormat()的方法displayJeroensFormat

                public void displayJeroensFormat()//@parameter double:
                {
                    System.out.println(jeroensFormat(10.5)); //Example for two decimals
                    System.out.println(jeroensFormat(10.95)); //Example for two decimals
                    System.out.println(jeroensFormat(10.00)); //Example for zero decimals
                    System.out.println(jeroensFormat(100.000)); //Example for zero decimals
                }
            

            会有以下输出:

            € 10,50
            € 10,95
            € 10,-
            € 100.000 (In Holland numbers bigger than € 999,- and wit no decimals don't have ,-)
            

            此代码使用您当前的货币。在我的情况下是荷兰,所以我的格式化字符串与美国的人不同。

            • 荷兰:999.999,99
            • 美国:999,999.99

            只需注意这些数字的最后 3 个字符。我的代码有一个 if 语句来检查最后 3 个字符是否等于“,00”。要在美国使用它,您可能必须将其更改为“.00”,如果它还不起作用的话。

            【讨论】:

              【解决方案13】:
              double amount =200.0;
              Locale locale = new Locale("en", "US");      
              NumberFormat currencyFormatter = NumberFormat.getCurrencyInstance(locale);
              System.out.println(currencyFormatter.format(amount));
              

              double amount =200.0;
              System.out.println(NumberFormat.getCurrencyInstance(new Locale("en", "US"))
                      .format(amount));
              

              显示货币的最佳方式

              输出

              $200.00

              如果你不想使用符号使用这个方法

              double amount = 200;
              DecimalFormat twoPlaces = new DecimalFormat("0.00");
              System.out.println(twoPlaces.format(amount));
              

              200.00

              这也可以使用(带千位分隔符)

              double amount = 2000000;    
              System.out.println(String.format("%,.2f", amount));          
              

              2,000,000.00

              【讨论】:

              【解决方案14】:

              我同意 @duffymo 的观点,即您需要使用 java.text.NumberFormat 方法来处理此类事情。您实际上可以在其中本地进行所有格式设置,而无需自己进行任何字符串比较:

              private String formatPrice(final double priceAsDouble) 
              {
                  NumberFormat formatter = NumberFormat.getCurrencyInstance();
                  if (Math.round(priceAsDouble * 100) % 100 == 0) {
                      formatter.setMaximumFractionDigits(0);
                  }
                  return formatter.format(priceAsDouble);
              }
              

              需要指出的几点:

              • 整个Math.round(priceAsDouble * 100) % 100 只是在解决双精度/浮点数的不准确性。基本上只是检查我们是否四舍五入到数百位(也许这是美国的偏见)是否还有剩余的美分。
              • 去除小数的诀窍是setMaximumFractionDigits() 方法

              无论您确定小数是否应该被截断的逻辑是什么,都应该使用setMaximumFractionDigits()

              【讨论】:

              • 关于 *100%100 偏向美国的观点,您可以使用 Math.pow(10, formatter.getMaximumFractionDigits()) 而不是硬编码的 100 来为区域设置使用正确的数字。 .
              【解决方案15】:

              我认为这对于打印货币来说很简单明了:

              DecimalFormat df = new DecimalFormat("$###,###.##"); // or pattern "###,###.##$"
              System.out.println(df.format(12345.678));
              

              产出:12,345.68 美元

              以及该问题的一种可能解决方案:

              public static void twoDecimalsOrOmit(double d) {
                  System.out.println(new DecimalFormat(d%1 == 0 ? "###.##" : "###.00").format(d));
              }
              
              twoDecimalsOrOmit((double) 100);
              twoDecimalsOrOmit(100.1);
              

              输出:

              100

              100.10

              【讨论】:

              • 您错过了帖子的重点。如果数字是整数,我不想显示任何小数。
              • DD。对不起,我根据问题更正了答案。
              【解决方案16】:

              我们通常需要做相反的事情,如果你的 json money 字段是一个浮点数,它可能是 3.1 、 3.15 或只是 3。

              在这种情况下,您可能需要对其进行四舍五入以正确显示(并且以后能够在输入字段上使用掩码):

              floatvalue = 200.0; // it may be 200, 200.3 or 200.37, BigDecimal will take care
              Locale locale = new Locale("en", "US");      
              NumberFormat currencyFormatter = NumberFormat.getCurrencyInstance(locale);
              
              BigDecimal valueAsBD = BigDecimal.valueOf(value);
                  valueAsBD.setScale(2, BigDecimal.ROUND_HALF_UP); // add digits to match .00 pattern
              
              System.out.println(currencyFormatter.format(amount));
              

              【讨论】:

                【解决方案17】:

                这是最好的方法。

                    public static String formatCurrency(String amount) {
                        DecimalFormat formatter = new DecimalFormat("###,###,##0.00");
                        return formatter.format(Double.parseDouble(amount));
                    }
                

                100 -> “100.00”
                100.1 -> “100.10”

                【讨论】:

                  【解决方案18】:

                  我疯了,写了自己的函数:

                  这会将整数转换为货币格式(也可以修改为小数):

                   String getCurrencyFormat(int v){
                          String toReturn = "";
                          String s =  String.valueOf(v);
                          int length = s.length();
                          for(int i = length; i >0 ; --i){
                              toReturn += s.charAt(i - 1);
                              if((i - length - 1) % 3 == 0 && i != 1) toReturn += ',';
                          }
                          return "$" + new StringBuilder(toReturn).reverse().toString();
                      }
                  

                  【讨论】:

                    【解决方案19】:
                      public static String formatPrice(double value) {
                            DecimalFormat formatter;
                            if (value<=99999)
                              formatter = new DecimalFormat("###,###,##0.00");
                            else
                                formatter = new DecimalFormat("#,##,##,###.00");
                    
                            return formatter.format(value);
                        }
                    

                    【讨论】:

                      【解决方案20】:

                      对于想要格式化货币,但又不希望它基于本地的人,我们可以这样做:

                      val numberFormat = NumberFormat.getCurrencyInstance() // Default local currency
                      val currency = Currency.getInstance("USD")            // This make the format not locale specific 
                      numberFormat.setCurrency(currency)
                      
                      ...use the formator as you want...
                      

                      【讨论】:

                        【解决方案21】:
                        NumberFormat currency = NumberFormat.getCurrencyInstance();
                        String myCurrency = currency.format(123.5);
                        System.out.println(myCurrency);
                        

                        输出:

                        $123.50
                        

                        如果您想更改货币,

                        NumberFormat currency = NumberFormat.getCurrencyInstance(Locale.CHINA);
                        String myCurrency = currency.format(123.5);
                        System.out.println(myCurrency);
                        

                        输出:

                        ¥123.50
                        

                        【讨论】:

                        • 如何得到相反的结果。来自格式化的非格式化原始字符串?
                        【解决方案22】:
                        double amount = 200.0;
                        
                        NumberFormat Us = NumberFormat.getCurrencyInstance(Locale.US);
                        System.out.println(Us.format(amount));
                        

                        输出
                        $200.00

                        【讨论】:

                          猜你喜欢
                          • 2017-03-23
                          • 1970-01-01
                          • 1970-01-01
                          • 2020-09-16
                          • 2022-11-14
                          • 1970-01-01
                          • 2015-10-24
                          • 1970-01-01
                          • 1970-01-01
                          相关资源
                          最近更新 更多