玖叶教程网

前端编程开发入门

Java修炼终极指南:20-21. double和整数


你知道吗,有些问题如果你知道解决方案就非常简单,如果你不知道就会觉得非常困难?这正是这种问题。解决方案非常简单,你可以在下面的代码中看到:

double value = -9.33543545;  
double fractionalPart = value % 1;  
double integralPart = value - fractionalPart;


这很简单;我认为你不需要进一步的解释。但这种方法并不完全准确。我的意思是整数部分是-9,但这样返回的是-9.0。而小数部分是-0.33543545,但返回的值是-0.3354354500000003。

如果我们需要一个更准确的结果,那么使用BigDecimal会更有用:

BigDecimal bd = BigDecimal.valueOf(value);  
int integralPart = bd.intValue();  
double fractionalPart = bd.subtract(  
       BigDecimal.valueOf(integralPart)).doubleValue();


这次,结果是-9和-0.33543545。


21. 测试double数字是否为整数

首先,让我们考虑以下预期结果(false表示double不是整数):

double v1 = 23.11;                    // false  
double v2 = 23;                       // true  
double v3 = 23.0;                     // true  
double v4 = Double.NaN;               // false  
double v5 = Double.NEGATIVE_INFINITY; // false  
double v6 = Double.POSITIVE_INFINITY; // false


很可能,测试double数字是否为整数的第一个解决方案是一个简单的类型转换,如下所示:

public static boolean isDoubleIntegerV1(double v) {  
  return v == (int) v;          
}


但是,还有其他几种选择。例如,我们可以依赖模数运算,如下所示:

public static boolean isDoubleIntegerV2(double v) {  
  return v % 1 == 0;  
}


或者,依赖Math.floor()和Double.isFinite()方法。如果给定的double是一个有限数,并且等于Math.floor()的结果,那么它就是一个整数:

public static boolean isDoubleIntegerV3(double v) {  
  return ((Math.floor(v) == v) && Double.isFinite(v));  
}


我们还可以用Math.ceil()替换这个等式:

public static boolean isDoubleIntegerV4(double v) {  
  return (Math.floor(v) == Math.ceil(v) && Double.isFinite(v));  
}


此外,我们可以将Double.isFinite()与Math.rint()结合起来,如下所示:

public static boolean isDoubleIntegerV5(double v) {  
  return ((Math.rint(v) == v) && Double.isFinite(v));  
}


最后,我们可以依赖Guava的DoubleMath.isMathematicalInteger():

public static boolean isDoubleIntegerV6(double v) {  
  return DoubleMath.isMathematicalInteger(v);  
}


但是,这些方法中哪一种性能更好?你更倾向于哪一种?好吧,让我们看看基准测试的结果怎么说:


图1.19 - 基准测试结果

基于这些结果,一个结论非常明显:依赖模数的方法应该避免。而且,Guava的解决方案似乎比其他方法稍慢一些。

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言