【问题标题】:How to format a number based on locale, while retaining all decimal points?如何根据区域设置格式化数字,同时保留所有小数点?
【发布时间】:2019-09-30 12:59:59
【问题描述】:

我正在尝试使用 DecimalFormat 转换双精度值的小数分隔符,同时保留原始数字的所有小数。 DecimalFormatter 接受格式为“0.##”的模式,例如。由于我必须使用具有不同小数的数字,因此这不起作用,因为始终需要在模式中指定小数位数。

我正在寻找解决此问题的方法。

我已经尝试过 String.format。 DecimaFormatter 和 NumberFormatter

我最理想的情况是:

  private static final ThreadLocal< DecimalFormat > formatter = new ThreadLocal< DecimalFormat >() 
  {
    @Override
    protected DecimalFormat initialValue() 
    {
    // n should be any number of decimals without having to specify them.
      return new DecimalFormat("0.0#n");     
    }
  };

一些例子:

DecimalFormat df = new DecimalFormat("0.0##");
System.out.println(df.format(2.456))
System.out.println(df.format(2.1));

结果:

2,456 -> Good
2,100 -> Not good

我想设置一个模式/正则表达式,它适用于小数点分隔符后任意位数的双精度,例如:

2,456 -> Good
2,1 -> Good
3,3453456345234 -> Good

【问题讨论】:

  • "...同时保留原始数字的所有原始小数点..." 一个数字最多只能有一个小数点(根据文化,可能是., 等)。一个数字可能有多个分组分隔符(在大多数讲英语的语言环境中,“千”分隔符,但并非所有文化都以相同的方式分组)(也可以是 ., 甚至是空格),但只有一位小数观点。你的意思是分组分隔符?还是小数?另外:请显示示例数字、格式不正确的数字以及它们*应该*看起来的样子。
  • 很抱歉给您带来了困惑。我更正了原帖。我的意思是分隔符后面的数字。
  • :-) 英文术语是“小数位”(但小数点后的数字也可以)。但同样,请提供示例、您得到的错误输出以及正确的输出。
  • @AthraelSoju 重读 Crowder 的第一条评论。您继续混淆将数字的小数部分与整数部分分开的小数分隔符concepts and terms,以及使整数部分更容易阅读的分组分隔符 .
  • @AthraelSoju 我假设您仍然希望小数点后至少有一位数字?否则 new DecimalFormat("") 似乎正在提供所需的行为?

标签: java format


【解决方案1】:

Java 中的数字(通常只是数字)没有固定的小数位数。 1.11.101.100 都是完全相同相同的数字。

您可以找出默认格式会使用多少个地方,例如:

String str = num.toString();
int decimal = str.indexOf('.');
int places = decimal <= 0 ? 0 : str.length - decimal;

...然后在使用格式化程序时指定那么多地方。

【讨论】:

    【解决方案2】:

    所以你有

    double[] floats = { 3.20, 4.500, 6.34, 1.0000 };
    BigDecimal[] fixeds = {
        new BigDecimal("3.20"),
        new BigDecimal("4.500"),
        new BigDecimal("6.34"),
        new BigDecimal("1.0000")
    };
    

    并希望将它们格式化,但已本地化。

    好消息是 BigDecimal 的定点数保持精度(使用字符串构造函数)。坏消息是浮点数总是一个近似值,是 2 的(负)幂之和。所以 3.20 实际上可能是 3.19999987 或 3.20000043。

    它们没有固定的小数。即使没有近似误差 3.2 == 3.20 == 3.200。

    所以转换为 BigDecimal(相当丑陋),并消除近似误差:1000*3.2 != 3200.0。

    BigDecimal value = new BigDecimal("5.1000");
    NumberFormat df = NumberFormat.getInstance(Locale.KOREA);
    df.setMinimumFractionDigits(value.getScale()); // 4
    String s = df.format(value);
    

    【讨论】:

      【解决方案3】:

      DecimalFormat 有 16 个setter methods 用于控制输出。您在构造函数中指定的模式字符串只是设置大多数这些值的便捷方式。

      要控制输出的语言环境,您可以在构造函数或setter method 中指定DecimalFormatSymbols

      由于您想要无限的小数位,而且您似乎想要至少一位小数,您需要调用一个 setter 方法,因为使用模式字符串无法指定 unlimited

      例子

      private static void test(Locale locale) {
          DecimalFormat fmt = new DecimalFormat("0.0", DecimalFormatSymbols.getInstance(locale));
          //fmt.setMaximumIntegerDigits(Integer.MAX_VALUE); // already set by pattern
          //fmt.setMinimumIntegerDigits(1);                 // already set by pattern
          //fmt.setMinimumFractionDigits(1);                // already set by pattern
          fmt.setMaximumFractionDigits(Integer.MAX_VALUE);
          //fmt.setGroupingUsed(false);                     // already set by pattern
      
          System.out.println(locale.toLanguageTag() + " (" + locale.getDisplayLanguage(Locale.US) +
                                                     " - " + locale.getDisplayCountry(Locale.US) + ")");
          System.out.println("  " + fmt.format(123456789));
          System.out.println("  " + fmt.format(2.456));
          System.out.println("  " + fmt.format(2.1));
          System.out.println("  " + fmt.format(3.3453456345234));
      }
      
      public static void main(String[] args) {
          test(Locale.US);
          test(Locale.GERMANY);
          test(Locale.forLanguageTag("ar-EG"));
      }
      

      输出 (OpenJDK 11.0.1)

      en-US (English - United States)
        123456789.0
        2.456
        2.1
        3.3453456345234
      de-DE (German - Germany)
        123456789,0
        2,456
        2,1
        3,3453456345234
      ar-EG (Arabic - Egypt)
        ١٢٣٤٥٦٧٨٩٫٠
        ٢٫٤٥٦
        ٢٫١
        ٣٫٣٤٥٣٤٥٦٣٤٥٢٣٤
      

      【讨论】:

        猜你喜欢
        • 2011-10-24
        • 1970-01-01
        • 1970-01-01
        • 2012-06-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多