我遇到了一个奇怪的案子。我尝试了两种不同的方法来输出Java中的双精度数。让结果为双数。第一个是:
DecimalFormat resFormat = new DecimalFormat("0.00E00f\n");
String strRes = resFormat.format(result);
if (strRes.contains("E-")) strRes = strRes.replace("E", "e");
else strRes = strRes.replace("E", "e+");
第二个是:
String strRes = String.format("%3.2ef\n",result);
我正在进行OJ挑战(中文,http://ac.jobdu.com/problem.php?pid=1514)。我试过了。保持所有其他代码完全相同,第一个输出通过所有测试,而第二个输出导致一些错误。
一个输出通过测试,而另一个输出失败。所以这两种解决方案的输出在某些情况下必须是不同的,对吧?为什么以及何时他们不同?
PS:两个代码段的输入都是有效的双数,既不是NaN也不是Infinity。
答案 0 :(得分:1)
尝试NaN,例如
result = 0.0/0.0;
第一种格式导致
NaNf
而第二个产生的东西打印在(我的)标准输出上:
�
这似乎是我的"替换字符":0xef 0xbf 0xbd当od' d。
来自DecimalFormat的Javadoc:" NaN被格式化为字符串,通常只有一个字符\ uFFFD。 "
同样无限:
result = 1.0/0.0;
结果
Infinityf
和
∞f
你可以(可能几乎无限制地)成功寻找其他差异的机会。这是一个比较,
static void cmp( double result ){
String strRes1 = String.format("%3.2ef",result);
DecimalFormat resFormat = new DecimalFormat("0.00E00f");
String strRes2 = resFormat.format(result);
if (strRes2.contains("E-")) strRes2 = strRes2.replace("E", "e");
else strRes2 = strRes2.replace("E", "e+");
if( ! strRes1.equals( strRes2 ) ){
System.out.println( strRes1 + " " + strRes2 );
System.out.println( result );
}
}
现在尝试找出一些差异:
for( double x = 1.0; true; x /= 2.0 ){ // hit Ctrl-C to terminate the program
cmp( x );
}
3.13e-02f 3.12e-02f
0.03125
1.27e-321f 1.26e-321f
1.265E-321
与w.r.t有一些区别四舍五入。
这非常好,但OJ网站上的原始问题是什么?尝试捕获JDK API中的细微差别是一个相当奇怪的挑战。你可以打赌,还有更多有趣的问题。