使用固定小数位数的工程符号格式化双精度数值

4

我想使用DecimalFormat格式化工程计数法(指数是3的倍数)和固定位数的小数。小数位数应该可以通过模式进行配置。

java.text.DecimalFormat类是否支持此功能?是否有替代方法?

这里是一个测试案例,输出为12.345E3而不是12.34E3:

public static void main(String[] args)
{
    Locale.setDefault(Locale.ENGLISH);
    DecimalFormat df = new DecimalFormat("##0.00E0");

    String realOutput = df.format(12345);
    String expected = "12.34E3";

    System.out.println(realOutput);
    if (Objects.equals(realOutput, expected))
    {
        System.out.println("OK");
    }
    else
    {
        System.err.println("Formatted output " + realOutput + " differs from documented output " + expected);
    }
}

3
谷歌是你的朋友。 - specializt
谷歌只是你的第二好朋友。你最好的朋友是几乎所有“内建”类/概念附带的优秀Javadoc文档。 - GhostCat
Javadoc没有帮助我找到解决方案。尝试找到一个工程符号和两个小数位的模式,适用于这两个数字:12345和1234。无论是工程符号不起作用还是小数位数不固定。 - Uli
@specializt:请将其写成答案。我会接受它作为正确答案。谢谢! - Uli
@specializt:是的,Google 是我们的好朋友!六年后,这个页面仍然是顶级搜索结果之一,一点就开! - Protean
2个回答

2
你应该使用以下内容:
DecimalFormat format = new DecimalFormat("##0.0E0");

http://docs.oracle.com/javase/7/docs/api/java/text/DecimalFormat.html中,您可以在“科学计数法”部分找到有关问题的答案。

科学计数法中的数字表示为底数和10的幂的乘积,例如,1234可以表示为1.234 x 10^3。底数通常在1.0 <= x < 10.0的范围内,但不一定是这样。 DecimalFormat可以通过模式指示格式化和解析科学计数法;目前没有创建科学计数法格式的工厂方法。在模式中,紧跟指数字符后面的一个或多个数字字符表示科学计数法。例如:“0.###E0”将数字1234格式化为“1.234E3”。

指数字符后的数字字符数给出最小的指数数字计数。没有最大值。使用本地化减号而不是模式的前缀和后缀来格式化负指数。这使得像“0.###E0 m/s”这样的模式成为可能。整数位数的最小值和最大值一起解释:如果整数位数的最大值大于它们的最小值且大于1,则强制指数为整数位数的最大值的倍数,并将最小整数位数解释为1。最常见的用途是生成工程符号,其中指数是三的倍数,例如“##0.#####E0”。使用此模式,数字12345格式为“12.345E3”,而123456格式为“123.456E3”。否则,通过调整指数来实现最小整数位数。例如:将0.00123格式化为“00.###E0”会产生“12.3E-4”。尾数中有效数字的数量是最小整数和最大小数位数之和,并且不受最大整数位数的影响。例如,使用“##0.##E0”格式化的12345为“12.3E3”。要显示所有数字,请将有效数字计数设置为零。有效数字的数量不影响解析。指数模式可能不包含分组分隔符。


我想要工程计数法,并保留2位小数。 - Uli
请尝试使用不同的数字进行模式匹配:12345、1.2和12.3。 - Uli
不,"0.00E0"将12345格式化为1.23E4,这不是工程符号表示法(只允许幂次为3的倍数的尾数)。 - Uli
尝试遵循文档:使用“##0.##E0”格式化的12345是“12.3E3”-> 这是错误的。使用“##0.##E0”格式化的12345应该是12.345E3。 - Uli
12.345E3是错误的,因为文档上说它应该是12.3E3。 - Uli
显示剩余5条评论

2
这个网站获取的内容:
private final static int PREFIX_OFFSET = 5;
private final static String[] PREFIX_ARRAY = {"f", "p", "n", "µ", "m", "", "k", "M", "G", "T"};

public static String convert(double val, int dp)
{
   // If the value is zero, then simply return 0 with the correct number of dp
   if (val == 0) return String.format("%." + dp + "f", 0.0);

   // If the value is negative, make it positive so the log10 works
   double posVal = (val<0) ? -val : val;
   double log10 = Math.log10(posVal);

   // Determine how many orders of 3 magnitudes the value is
   int count = (int) Math.floor(log10/3);

   // Calculate the index of the prefix symbol
   int index = count + PREFIX_OFFSET;

   // Scale the value into the range 1<=val<1000
   val /= Math.pow(10, count * 3);

   if (index >= 0 && index < PREFIX_ARRAY.length)
   {
      // If a prefix exists use it to create the correct string
      return String.format("%." + dp + "f%s", val, PREFIX_ARRAY[index]);
   }
   else
   {
      // If no prefix exists just make a string of the form 000e000
      return String.format("%." + dp + "fe%d", val, count * 3);
   }
}

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