使用DecimalFormat格式化大双数

我试图使用DecimalFormat格式化双数字只打印2位小数的数字,如果它有小数部分,我想打印数字原样。 当数字很小时,下面的代码工作正常但数字很大,它没有按预期工作。

  DecimalFormat df = new DecimalFormat("#.##"); //have tried just # too double d1 = 56789d; System.out.println(df.format(d1)); //works fine - prints 56789 double d2 = 1234567879123456789d; System.out.println(df.format(d2)); // does not work 

第二个输出1234567879123456770而我想要1234567879123456789 。 对于带小数部分的双精度值,我只想保留两个小数点。

什么出错的建议?

关于为什么解析值偏离19在于如何表示double值,作为具有53位精度的IEEE浮点数 。 也就是说,对于输入时的较大值,精度实际上大于1Math.ulp方法,对于“最后位置的单位”,给出了最接近的double值可以在其参数的大小上分开。

 double d2 = 1234567879123456789d; DecimalFormat df = new DecimalFormat("#.##"); System.out.println(Math.ulp(d2)); System.out.println(df.format(d2)); 

这输出

 256.0 1234567879123456770 

因此,您获得与您在源代码中键入的数字最接近的double值。 JLS的3.10.2节涵盖double文字:

float和double类型的元素是可以分别使用IEEE 754 32位单精度和64位双精度二进制浮点格式表示的值。

对于类Float的方法valueOf和包java.lang的类Double,描述了从浮点数的Unicode字符串表示到内部IEEE 754二进制浮点表示的正确输入转换的详细信息。

并参考Double.valueOf javadocs :

s被视为代表通常的“计算机化科学记数法”中的精确十进制值或精确的hex值; 然后,这个精确的数值在概念上被转换为“无限精确”的二进制值,然后通过IEEE 754浮点运算的通常的舍入到最接近的规则舍入为double类型[…]

此外,此值仍在long值范围内,这仍将正确表示整数值。

 long l2 = 1234567879123456789L; DecimalFormat df = new DecimalFormat("#.##"); System.out.println(df.format(l2)); 

这输出

 1234567879123456789 

您的文字有19个十进制数字,但双精度只有15.9十进制数字。