【问题标题】:Java: Format number in millionsJava:以百万为单位的格式数字
【发布时间】:2010-10-06 11:28:31
【问题描述】:

有没有办法使用 DecimalFormat(或其他一些标准格式化程序)来像这样格式化数字:

1,000,000 => 100 万

1,234,567 => 123 万

1,234,567,890 => 1234.57M

基本上将某个数字除以 100 万,保留 2 个小数位,并在末尾打一个“M”。我考虑过创建一个新的 NumberFormat 子类,但它看起来比我想象的要复杂。

我正在编写一个具有如下格式方法的 API:

public String format(double value, Unit unit); // Unit is an enum

在内部,我将 Unit 对象映射到 NumberFormatters。实现是这样的:

public String format(double value, Unit unit)
{
    NumberFormatter formatter = formatters.get(unit);
    return formatter.format(value);
}

请注意,正因为如此,我不能指望客户端除以 100 万,而且我不能只使用 String.format() 而不将其包装在 NumberFormatter 中。

【问题讨论】:

  • 你想只处理 M(ega) 还是 (G)iga、(T)era 等?
  • 它实际上代表证券的交易量,所以它是 M(illions),可能是 B(illions),但我会很高兴只用 M。
  • This related question 最近受到了很多关注(由于赏金)。

标签: java formatting numeric numericupdown


【解决方案1】:
String.format("%.2fM", theNumber/ 1000000.0);

有关详细信息,请参阅String.format javadocs

【讨论】:

  • 以防万一:改用 1000000.0。
  • 次要的 nitpick,看起来他的代码使用的是 long 或 int,因此您可以省去浮点运算:
  • 如果我不考虑浮点数学,我会得到一个整数,根本没有小数位。我们至少需要 2 个。
  • 这行得通,但我仍然需要用 NumberFormat 对象包装它,因为我忘了提到一个额外的约束。基本上有一个 MAP[Type => NumberFormatter] 需要很好地配合。
  • 好吧,我从来没有使用过 NumberFormatter...所以我不知道最简单的包装方法。
【解决方案2】:

请注意,如果您有BigDecimal,则可以使用movePointLeft 方法:

new DecimalFormat("#.00").format(value.movePointLeft(6));

【讨论】:

    【解决方案3】:

    这是我创建的 NumberFormat 的子类。看起来它可以完成这项工作,但我不完全确定这是最好的方法:

    private static final NumberFormat MILLIONS = new NumberFormat()
    {
        private NumberFormat LOCAL_REAL = new DecimalFormat("#,##0.00M");
    
        public StringBuffer format(double number, StringBuffer toAppendTo, FieldPosition pos)
        {
            double millions = number / 1000000D;
            if(millions > 0.1) LOCAL_REAL.format(millions, toAppendTo, pos);
    
            return toAppendTo;
        }
    
        public StringBuffer format(long number, StringBuffer toAppendTo, FieldPosition pos)
        {
            return format((double) number, toAppendTo, pos);
        }
    
        public Number parse(String source, ParsePosition parsePosition)
        {
            throw new UnsupportedOperationException("Not implemented...");
        }
    };
    

    【讨论】:

    • 我喜欢 Outlaw 的解决方案,特别是因为它还可以创建 k/M/G“人类可读”格式,而无需此 api 的用户进行计算。他总是得到最短的号码。 999999 999.99k 999.99M 999.99G 999.99T
    【解决方案4】:

    为什么不简单呢?

    DecimalFormat df = new DecimalFormat("0.00M");
    System.out.println(df.format(n / 1000000));
    

    【讨论】:

    • 分割需要封装在格式化程序里面。我想我会更新问题以更清楚地解释我遇到的问题。
    【解决方案5】:

    对于那些希望将给定数字转换为人类可读形式的人。

    public static String getHumanReadablePriceFromNumber(long number){
    
        if(number >= 1000000000){
            return String.format("%.2fB", number/ 1000000000.0);
        }
    
        if(number >= 1000000){
            return String.format("%.2fM", number/ 1000000.0);
        }
    
        if(number >= 100000){
            return String.format("%.2fL", number/ 100000.0);
        }
    
        if(number >=1000){
            return String.format("%.2fK", number/ 1000.0);
        }
        return String.valueOf(number);
    
    }
    

    【讨论】:

      【解决方案6】:

      看看ChoiseFormat

      更简单的方法是使用自动除以 1m 的包装器。

      【讨论】:

      • 看了一下文档,但我真的不确定这对我有什么帮助。似乎 ChoiceFormat 基本上包含一堆格式,并且以某种方式将输入与其中一种子格式相匹配。我想我希望所有输入都得到相同的处理。
      【解决方案7】:

      现在,您应该使用 ICU 的 CompactDecimalFormat,它将本地化​​非英语语言环境的格式化结果。其他语言环境可能不使用“百万”后缀。

      This functionality will be standard Java in JDK 12CompactNumberFormat

      【讨论】:

        【解决方案8】:

        在 Kotlin 语言中,可以做扩展函数:

        fun Long.formatToShortNumber(): String {
            return when {
                this >= 1000000000 -> String.format("%.2fB", this / 1000000000.0)
                this >= 1000000 -> String.format("%.2fM", this / 1000000.0)
                this >= 1000 -> String.format("%.2fK", this / 1000.0)
                else -> this.toString()
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多