特别是在Java中,如何确定double
是否为整数?为了澄清,我想知道如何确定double实际上不包含任何分数或小数。
我主要关注的是浮点数的性质。我想到的方法(以及我通过Google找到的方法)基本遵循以下格式:
double d = 1.0;
if((int)d == d) {
//do stuff
}
else {
// ...
}
我当然不是浮点数及其表现的专家,但我的印象是因为double
只存储了数字的近似,{ {1}}条件只会输入某些的时间(甚至可能是当时的多数)。但我正在寻找一种方法,无论if()
值如何存储在系统中,都可以保证100%的工作时间。
这可能吗?如果是这样,如何以及为什么?
答案 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之间足够接近。