如何准确判断double是否为整数?

时间:2012-08-22 16:44:39

标签: java floating-point

特别是在Java中,如何确定double是否为整数?为了澄清,我想知道如何确定double实际上不包含任何分数或小数。

我主要关注的是浮点数的性质。我想到的方法(以及我通过Google找到的方法)基本遵循以下格式:

double d = 1.0;
if((int)d == d) {
    //do stuff
}
else {
    // ...
}

我当然不是浮点数及其表现的专家,但我的印象是因为double只存储了数字的近似,{ {1}}条件只会输入某些的时间(甚至可能是当时的多数)。但我正在寻找一种方法,无论if()值如何存储在系统中,都可以保证100%的工作时间。

这可能吗?如果是这样,如何以及为什么?

5 个答案:

答案 0 :(得分:7)

double可以存储某些值的精确表示,例如小整数和(负或正)2的幂。

如果它确实存储了一个确切的整数,那么((int)d == d)工作正常。事实上,对于任何32位整数i,(int)((double)i) == i,因为双精度可以完全代表它。

请注意,对于非常大的数字(大小大于约2 ** 52),double将始终显示为整数,因为它将不再能够存储任何小数部分。例如,如果您尝试转换为Java long,则会产生影响。

答案 1 :(得分:2)

怎么样

 if(d % 1 == 0)

这是有效的,因为所有整数都是0模1。

编辑对于那些因为速度慢而反对这一点的人,我对它进行了描述,发现它比投射慢约3.5倍。除非这是一个紧密的循环,否则我认为这是一种更好的解决方法,因为它非常清楚你正在测试什么,并且不需要任何关于整数转换的语义。

我通过在

的javac上运行时间来描述它
class modulo {
    public static void main(String[] args) {
        long successes = 0;
        for(double i = 0.0; i < Integer.MAX_VALUE; i+= 0.125) {
            if(i % 1 == 0)
                successes++;
        }
        System.out.println(successes);
    }
}

VS

class cast {
    public static void main(String[] args) {
        long successes = 0;
        for(double i = 0.0; i < Integer.MAX_VALUE; i+= 0.125) {
            if((int)i == i)
                successes++;
        }
        System.out.println(successes);
    }
}

最后都印有2147483647 Modulo在我的机器上花了189.99s - Cast花了54.75s。

答案 2 :(得分:1)

使用if((int)d == d)的方法应始终适用于任何32位整数。为了使其最多工作64位,您可以使用if((long)d == d,这实际上是相同的,只是它占了更大的数字。如果d大于最大long值(或小于最小值),则保证它是精确整数。然后可以按如下方式构造测试d是否为整数的函数:

boolean isInteger(double d){
    if(d > Long.MAX_VALUE || d < Long.MIN_VALUE){
        return true;
    } else if((long)d == d){
        return true;
    } else {
        return false;
    }
}

如果浮点数是一个整数,那么它就是该整数的精确表示。

答案 3 :(得分:1)

if(new BigDecimal(d).scale() <= 0) {
    //do stuff
}

答案 4 :(得分:-2)

双打是具有二进制指数的二进制分数。您无法确定整数是否可以精确地表示为double,尤其是如果它是从其他值计算的。

因此,接近这一点的正常方法是说它需要足够接近&#34;到一个整数值,其中足够接近通常意味着&#34;在X%&#34; (其中X相当小)。

即。如果X为1,那么1.98和2.02都被认为足够接近2.如果X是0.01则需要在1.9998和2.0002之间足够接近。