Java:为什么乘以大的正数会导致负结果?

标签 java math types

<分区>

我看到一些奇怪的行为与 Java 相乘整数。我正在做一些编码练习,并遇到了以下 fizz buzz 类型的练习。要求:给定一个整数,编写一个函数,找出小于给定整数的每一个 3 的倍数的乘积,除外任何 5 的倍数。例如,给定 17,我们想要返回 12* 9*6*3(=1944)。我写了以下内容:

public int findProduct(int limit) { 
    int product = 1;
    for(int n = 3; n < limit; n = n + 3) {
        if (n % 5 != 0) {
            product = product * n;
        }
    }
    return product;
}

这对小数字来说效果很好。然而在测试中我发现,一旦你超过 33,返回值就会偏离。例如,如果我调用限制为 36 的函数,它会返回 -1.466221696E9。这就是我感到困惑的地方。我乘以正数 整数,结果不知为何是负数。

但是,我发现如果您声明一个 double ,它似乎总是返回正确的结果。

public double findProduct(int limit) { 
    double product = 1;
    for(int n = 3; n < limit; n = n + 3) {
        if (n % 5 != 0) {
            product = product * n;
        }
    }
    return product;
}

我的问题是:为什么整数会发生这种情况?double 类型有什么不同之处使其能够正确执行?

最佳答案

让我们以 Integer 为例来研究一下。

Integer.MAX_VALUE 可以表示为 01111111111111111111111111111111,这是一个 32 位长字符串(包括符号位)。现在,如果您碰巧将 1 添加到上述字符串,它会生成 10000000000000000000000000000000,这与 Integer.MIN_VALUE 相同。这称为 Integer 的溢出。

System.out.println(Integer.toBinaryString(Integer.MAX_VALUE));
// 1111111111111111111111111111111

根据 Integer#toBinaryString :

The unsigned integer value is the argument plus 232 if the argument is negative; otherwise it is equal to the argument. This value is converted to a string of ASCII digits in binary (base 2) with no extra leading 0s.

这就是为什么您看不到符号位,但 Integer.MAX_VALUE 的实际值为 01111111111111111111111111111111 的原因。现在看看这段代码:

System.out.println(Integer.toBinaryString(Integer.MAX_VALUE + 1));
// 10000000000000000000000000000000
System.out.println(Integer.toBinaryString(Integer.MIN_VALUE));
// 10000000000000000000000000000000

两个数字的输出是相同的。 Java 不能防止 Integer 溢出。应该由开发人员负责。那么这个问题的可能解决方案是什么?您可以使用其他数据类型,例如 longBigInteger .以下是您可能感兴趣的最大值:

System.out.println(Integer.MAX_VALUE); // 2147483647
System.out.println(Long.MAX_VALUE); // 9223372036854775807
System.out.println(Double.MAX_VALUE); // 1.7976931348623157E308
System.out.println(Float.MAX_VALUE); // 3.4028235E38

一旦 Integer 达到 MAX_VALUE,它就会开始溢出,最终会变成负值。

关于Java:为什么乘以大的正数会导致负结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55323173/

相关文章:

java - 如何使用listview.GetItemAtPosition(e.Position)获取用户点击的ListView项的数据?

python - 过滤元组列表以删除所有奇数或总和小于 80 的列表

c++ - 对象 vector 无法编译

c++ - 如何在 C 或 C++ 中构建大小为 n 的全新数据类型而不使用任何用户定义的数据类型?

java - Redis 集群与 Spring Boot 集成

java - Spring MVC,用IF语句将数据发送到MySQL

c++ - 给定一组点的特征和 SVD 找到最佳拟合平面

algorithm - 根据图案(展开)折叠一张纸并给出层的顺序

c - 类型兼容性约定和函数声明

java - 初始化对象内联并作为参数传递 - java