Java:为什么将大正数相乘会导致负数结果? [英] Java: why does multiplying large positive number cause negative results?

查看:72
本文介绍了Java:为什么将大正数相乘会导致负数结果?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我看到一些将Java与整数相乘的奇怪行为.我正在做一些编码练习,然后进行了以下嘶嘶声类型的练习.要求:给定一个整数,编写一个函数,该函数查找小于给定整数的3的每一个倍数的乘积,为5的任何倍数.例如,给定17,我们要返回12 *9 * 6 * 3(= 1944).我写了以下内容:

I’m seeing some strange behavior multiplying integers with Java. I was doing some coding exercises and came upon the following fizz buzz type of exercise. The requirements: Given an integer, write a function that finds the product of every multiple of 3 which is smaller than the given integer, except any multiple of 5. Eg, given 17 we want to return 12*9*6*3 (= 1944). I wrote the following:

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.这就是我感到困惑的地方.我要乘以正数整数,结果是负数.

This works just fine for small numbers. However in testing I found that once you get above 33 somehow the return value is way off. For example if I call the function with a limit of 36, it returns -1.466221696E9. This is where I get confused. I am multiplying positive integers and the result is somehow negative.

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

However, I discovered that if you declare a double it seems to always return the correct result.

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类型正确执行的double类型有何不同?

My question is: Why is this happening with the integers and what is different about the double type that makes it perform correctly?

推荐答案

让我们以 Integer 的示例为例进行研究.

Let's examine this by taking an example of Integer.

Integer.MAX_VALUE 可以表示为 01111111111111111111111111111111 ,它是一个 32 位长的字符串(包括符号位).现在,如果您碰巧在上面的字符串中添加了 1 ,则结果为 10000000000000000000000000000000000000 ,它与 Integer.MIN_VALUE 相同.这称为 Integer 的溢出.

Integer.MAX_VALUE can be represented as 01111111111111111111111111111111 which is a 32 bit long string(including sign bit). Now if you happen to add 1 to the above string, it results in 10000000000000000000000000000000 which is same as Integer.MIN_VALUE. This is called overflow of Integer.

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

根据 Integer#toBinaryString :

无符号整数值是参数加上2 32 (如果参数为负);否则等于参数.此值将转换为二进制(以2为基)的ASCII数字字符串,且没有多余的前导0.

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 的原因.现在看一下这段代码:

So that's why you can't see the sign bit but the real value of Integer.MAX_VALUE is 01111111111111111111111111111111. Now take a look at this code:

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

两个数字的输出相同.Java不能防止 Integer 溢出.开发人员应该注意这一点.那么,该问题的可能解决方案是什么?您可以使用其他数据类型,例如 long

The output of both the numbers is same. Java doesn't protect against Integer overflow. It is the developer who should take care of this. So what could be the possible solution to this problem? You can use other data types such as long or BigInteger. Here are the max values you might be interested in:

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 ,它将开始溢出,最终将返回负值.

Once the Integer reaches MAX_VALUE it will start to overflow and you will end up in negative value.

这篇关于Java:为什么将大正数相乘会导致负数结果?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆