在Java中将int转换为double,然后再转换回int

6

快速问题。

这个总是正确的吗?

int i = ...;
double d = i;
if (i == (int) d) ...

或者我需要进行四舍五入以确保结果正确?
if (i == Math.round(d)) ...
3个回答

8

是的,所有可能的int值都可以安全地往返于double

您可以使用以下代码进行验证:

    for (int i = Integer.MIN_VALUE; ; i++) {
        double d = i;
        if (i != (int) d) {
            throw new IllegalStateException("i can't be converted to double and back: " + i);
        }
        if (i == Integer.MAX_VALUE) {
            break;
        }
    }

请注意,我没有使用普通的 for 循环,因为它要么会跳过 Integer.MAX_VALUE,要么会无限循环。
请注意,对于 int/floatlong/double 来说,情况并一样!

1
@delnan:使用该条件将跳过对“Integer.MAX_VALUE”的测试。 - Joachim Sauer
@JoachimSauer 感谢您的回答。@delnan,我已经检查过了,在我的电脑上运行了20秒。 - Sergey Aslanov
@JoachimSauer 嗯,对于 int/floatlong/double 来说,这更多是容量问题,而不是舍入问题,对吧? - Sergey Aslanov
@JustYo,这是容量问题导致了表示中的舍入误差。通常称为舍入误差。 - Peter Lawrey
@JustYo ,浮点数在2^24左右会出现问题。例如:int i = 16777217; float f = i; int d = (int)f; 现在 d 的值为 16777216! - nos

1

如果你的电脑速度较慢或者没有时间运行循环来自己检查,Java语言规范中相关部分在这里§ 5.1.2 Widening Conversions

以下19种基本类型的特定转换被称为扩展原始类型转换:

  • byte到short、int、long、float或double
  • short到int、long、float或double
  • char到int、long、float或double
  • int到long、float或double
  • long到float或double
  • float到double

扩展原始类型转换不会丢失有关数值总体大小的信息。实际上,从整数类型到另一个整数类型和从浮点数到双精度浮点数的扩展转换根本不会丢失任何信息;数值是完全保留的。[...]

(以下章节§ 5.1.3 缩小原始类型转换确保双向转换,即double -> int,也不会丢失任何信息。)


我检查了整型和浮点型之间的转换,发现在-2147483647处出现错误。经过一轮操作后,变成了-2147483648。 - Sergey Aslanov
正确的,float -> int 但是这是一种可能会丢失信息的缩小转换。 - aioobe

0

一种基于Joachim的解决方案的变体。

int i=Integer.MIN_VALUE;
do {
    if(i != (int)(double) i) throw new AssertionError(i + " != (int)(double) "+i);
} while(i++ < Integer.MAX_VALUE);

查找导致转换为浮点数时出错的最小值。

int i = 0;
do {
    if(i != (int)(float) i) throw new AssertionError(i + " != (int)(float) "+i);
} while(i++ < Integer.MAX_VALUE);

打印

java.lang.AssertionError: 16777217 != (int)(float) 16777217

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