我试图使用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
Run Code Online (Sandbox Code Playgroud)
1234567879123456770我想要的第二个输出1234567879123456789.对于带小数部分的双精度值,我只想保留两个小数点.
什么是错的任何建议?
关于为什么解析的值被关闭的解释19在于如何double表示值,作为具有53位精度的IEEE浮点数.也就是说,对于输入的大值,精度实际上大于1.的方法Math.ulp,对"最后一名单位",给出最接近的double值可以在它的参数的大小分开.
double d2 = 1234567879123456789d;
DecimalFormat df = new DecimalFormat("#.##");
System.out.println(Math.ulp(d2));
System.out.println(df.format(d2));
Run Code Online (Sandbox Code Playgroud)
这输出
256.0
1234567879123456770
Run Code Online (Sandbox Code Playgroud)
因此,您获得的double值与您在源代码中键入的数字最接近. JLS的3.10.2节涵盖了double文字:
float和double类型的元素是可以分别使用IEEE 754 32位单精度和64位双精度二进制浮点格式表示的值.
有关从浮点数的Unicode字符串表示到内部IEEE 754二进制浮点表示的正确输入转换的详细信息,请参阅类Float的方法valueOf和包java.lang的类Double.
s被视为代表通常的"计算机化科学记数法"中的精确十进制值或精确的十六进制值; 然后,这个精确的数值在概念上被转换为"无限精确"的二进制值,然后通过IEEE 754浮点运算的通常的舍入到最接近的规则舍入为double类型[...]
此外,此值仍在long值范围内,这仍将正确表示整数值.
long l2 = 1234567879123456789L;
DecimalFormat df = new DecimalFormat("#.##");
System.out.println(df.format(l2));
Run Code Online (Sandbox Code Playgroud)
这输出
1234567879123456789
Run Code Online (Sandbox Code Playgroud)