使用DecimalFormat的科学记数法中有效数字的个数



我正试图完全理解DecimalFormat的确切行为。我目前正在用这个类的科学符号能力做一些测试。我遇到了一个问题,如何调整科学记数法中有效数字的确切数量。根据Java 7的Javadoc:

尾数中有效数字的个数是最小整数和最大分数位数,并且不受最大整数位数。例如,用"##0.##E0"格式化的12345"12.3 e3"。若要显示所有数字,请将有效数字计数设置为零。有效数字的个数不影响解析。

因此,我测试它:

DecimalFormat formatone = new DecimalFormat("##0.##E0");
System.out.println(formatone.format(toF));

得到如下输出:

12,345E3

根据我刚才展示的Javadoc的摘录,我认为我应该获得

12.3E3

我做错了什么吗?我理解错了吗?

提前感谢您的所有澄清:-)

我已经打印了大小写为"##0 "的最小/最大整数/分数位数的值。##E0"并验证@Agemen:

给出的结果。
DecimalFormat df = new DecimalFormat( "##0.##E0" );
System.out.printf("getMinimumIntegerDigits=%dn", df.getMinimumIntegerDigits() );
System.out.printf("getMaximumIntegerDigits=%dn", df.getMaximumIntegerDigits() );
System.out.printf("getMinimumFractionDigits=%dn", df.getMinimumFractionDigits() );
System.out.printf("getMaximumFractionDigits=%dn", df.getMaximumFractionDigits() );
double v = 12345;
System.out.printf("s=%fn", v );
System.out.printf("r=%sn", df.format(v) );

,结果为:

getMinimumIntegerDigits=1
getMaximumIntegerDigits=3
getMinimumFractionDigits=0
getMaximumFractionDigits=2
s=12345.000000
r=12.345E3

在我看来,这是一个错误在Java实现或在文档中,没有获得预期的结果。

对于@JoopEggen答案中给出的例子,它不适用,因为模式"##0.#####E0"的最大分数位数等于5。

实际上,期望的字符串是使用模式"##0.E0"获得的。

错误可能在文件DecimalFormat.java, at statement:

digitList.set(isNegative, number,
useExponentialNotation ? 
maxIntDigits + maxFraDigits : maxFraDigits,
!useExponentialNotation);

其中添加的"maxIntDigits + maxFraDigits"应该是"minIntDigits + maxFraDigits",以符合java文档

忽略the mantissa is the sum of the minimum integer and maximum fraction digits

要得到想要的输出,需要设置这些值:

    DecimalFormat formatone = new DecimalFormat("##0.##E0");
    formatone.setMinimumIntegerDigits(2);
    formatone.setMaximumFractionDigits(0);
    System.out.println(formatone.format(12345));

从http://docs.oracle.com/javase/6/docs/api/java/text/DecimalFormat.html衍生出以下"解释"。一个奇迹。

最小整数位数和最大整数位数一起解释:

如果最大整数位数大于最小整数位数且大于1,则强制指数为最大整数位数的倍数,并且最小整数位数被解释为1。最常见的用法是生成工程符号,其中指数是3的倍数,例如,"##0.#####E0"。使用这种模式,数字12345格式化为"12.345E3",123456格式化为"123.456E3"。

在设置小数格式时,请确保控制小数和分组分隔符。

这是一种方法(注意所有的格式模式选择):

@Test
public void test() {        
    double toF = 12345;
    DecimalFormatSymbols decimalFormatSymbols = new DecimalFormatSymbols();
    decimalFormatSymbols.setDecimalSeparator('.');
    decimalFormatSymbols.setGroupingSeparator(',');
    System.out.println((new DecimalFormat("#.#E0", decimalFormatSymbols)).format(toF));
    System.out.println((new DecimalFormat("#0.#E0", decimalFormatSymbols)).format(toF));
    System.out.println((new DecimalFormat("##0.#E0", decimalFormatSymbols)).format(toF));
    System.out.println((new DecimalFormat("##0.##E0", decimalFormatSymbols)).format(toF));
    System.out.println((new DecimalFormat("##0.###E0", decimalFormatSymbols)).format(toF));
}

输出:

1.2E4
1.23E4
12.34E3
12.345E3
12.345E3

您可以在Java 8 API文档中获得更多信息,该文档可能比您目前看到的文档更新。

最新更新