一个双等号是否总是会转换成整数?

13

如果一个双精度浮点数等于一个整数,那么它是否总是可以转换为该整数呢?(假设该双精度浮点数不会导致溢出)。例如:Math.ceil() 将返回一个等于整数的双精度浮点数。假设没有发生溢出,那么它总是可以转换为与其相等的整数吗?

如果不能,那么如何将一个double四舍五入为一个intlong


+1:有趣的问题。我会认为答案是“是”,但可能有一些我没有考虑到的边缘情况。 - Oliver Charlesworth
5个回答

9

4
尾数代表53位,因为最高位隐含为1。 - Peter Lawrey

6

是的,它将完全转换。这在JLS的第5.1.3节中有所描述,其中提到:

否则,如果浮点数不是无穷大,则使用IEEE 754朝零舍入模式将浮点值四舍五入为整数值V...

由于您的double恰好等于int,因此“四舍五入”值就是完全相同的值,但您可以阅读规范以获取详细信息。


1

我相信是这样的,但你可以自己测试一下:

public static void main(String... args) throws Exception {
    int interactions = Integer.MAX_VALUE;
    int i = Integer.MIN_VALUE;
    double d = Integer.MIN_VALUE;
    long init = System.currentTimeMillis();
    for (; i < interactions; i++, d++)
        if (!(i == (int) Math.ceil(d)))
            throw new Exception("something went wrong with i=" + i + " and d=" + d + ", Math.ceil(d)="+Math.ceil(d));

    System.out.println("Finished in: "+(System.currentTimeMillis() - init)+"ms");
}

我非常确定,如果你这样做很长时间,你的舍入误差会引起问题。(即0.1无法精确表示) - Peter Lawrey
使用经验测试来进行这种交互是不好的,因为它在大多数情况下会得出错误的结论。 - jb.

1
所有可能的int值都可以用double表示,且不会出现错误。向上取整的最简单方法是使用Math.ceil(),例如:
double d = 
long l = (long) Math.ceil(d); // note: could overflow.

3
所有的 int 值都可以,但不是所有的 long 值都可以。 - Oliver Charlesworth

1
根据经验来看,答案似乎是肯定的 - 注意它也适用于 i2 = (int) d;
public static void main(String[] args) {
    for (int i = Integer.MIN_VALUE + 1; i < Integer.MAX_VALUE; i++) {
        double d = i;
        int i2 = (int) Math.ceil(d);
        if (i != i2) {
            System.out.println("i=" + i + " and i2=" + i2); //Never executed
        }
    }
}

修改为从Integer.MIN_VALUE开始。 - assylias
使用经验测试来进行这种交互是不好的,因为它在大多数情况下会得出错误的结论。 - jb.
1
测试是全面的(即测试了所有情况),我不认为有问题。如果它只测试了所有可用整数的部分子集,我可能会同意...... - assylias
@jb,这实际上不是经验论证。它通过证明每个整数都成立来证明该条件适用于所有整数。(好吧,你需要分别展示MIN_VALUE和MAX_VALUE才能涵盖它们全部。) - Sean Owen
2
如果我们不知道这种行为在 JLS 中被定义,它也可能因 JVM 而异。因此,要证明它,您必须在所有最近和未来的 JVM 上进行检查。我曾经见过做过这种测试并说“它有效”的人,但在他们投入生产后就不起作用了。 - jb.
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接