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

时间:2011-12-14 13:57:53

标签: java decimalformat

我试图完全理解DecimalFormat的确切行为。我目前正在用这个类的科学记谱功能进行一些测试。而且我在调整科学记数法中有效位数的确切问题时遇到了问题。根据Java 7的Javadoc:

  

尾数中的有效位数是。的总和   最小整数和最大分数,并且不受影响   最大整数位数。例如,12345格式为“## 0。## E0”   是“12.3E3”。要显示所有数字,请将有效数字设置为   零。有效位数不会影响解析。

因此,我正在测试它:

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

我获得以下输出:

12,345E3

根据我刚刚展示的Javadoc的摘录,我想我应该获得

12.3E3

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

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

4 个答案:

答案 0 :(得分:6)

在“ ## 0。## E0”的情况下,我已经打印了最小/最大整数/分数位数的值,并验证了@Agemen给出的结果:

DecimalFormat df = new DecimalFormat( "##0.##E0" );
System.out.printf("getMinimumIntegerDigits=%d\n", df.getMinimumIntegerDigits() );
System.out.printf("getMaximumIntegerDigits=%d\n", df.getMaximumIntegerDigits() );
System.out.printf("getMinimumFractionDigits=%d\n", df.getMinimumFractionDigits() );
System.out.printf("getMaximumFractionDigits=%d\n", df.getMaximumFractionDigits() );

double v = 12345;
System.out.printf("s=%f\n", v );
System.out.printf("r=%s\n", 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中,位于语句:

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

添加的“ maxIntDigits + maxFraDigits”应为“ minIntDigits + maxFraDigits”,以与Java文档保持一致。

答案 1 :(得分:2)

您忽略了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));

答案 2 :(得分:0)

来自http://docs.oracle.com/javase/6/docs/api/java/text/DecimalFormat.html引发了以下“解释”。人们不禁要问。

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

如果最大整数位数大于其最小数且大于1,则强制指数为最大整数位数的倍数,并将最小整数位数解释为1。最常见的用途是生成工程符号,其中指数是三的倍数,例如“## 0。##### E0”。使用此模式,数字12345格式为“12.345E3”,123456格式为“123.456E3”。

答案 3 :(得分:0)

格式化小数位时,请确保控制小数位和分组分隔符。

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

@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 Documentation中获得更多信息,这些信息可能比您到目前为止所看到的信息要新。