Java:为什么“长”数会变成负数?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33689454/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 22:00:08  来源:igfitidea点击:

Java: Why does "long" number get negative?

javalong-integer

提问by Slimu

I have this code:

我有这个代码:

    long i = 0;
    while (true) {  
        i += 10*i + 5;
        System.out.println(i);
        Thread.sleep(100);      
    }

Why does the long iget negative after a few prints? If the range is exceeded, shouldn't an error occur?

为什么long i打印几次后会变成负片?如果超出范围,不应该发生错误吗?

回答by Slimu

Java doesn't throw an error if you increase a number after its maximum value. If you wish to have this behaviour, you could use the Math.addExact(long x, long y)method from Java 8. This method will throw an ArithmeticExceptionif you pass the Long.MAX_VALUE.

如果在最大值之后增加一个数字,Java 不会抛出错误。如果你希望有这种行为,你可以使用Math.addExact(long x, long y)Java 8 中的方法。ArithmeticException如果你传递Long.MAX_VALUE.

The reason why Java doesn't throw an exception and you receive negative numbers has to do with the way numbers are stored. For a long primitive the first byte is used for indicating the sign of the number (0 -> positive, 1 -> negative), while the rest are used for the numeric value. This means that Long.MAX_VALUEwhich is the biggest positive value will be stored as 01111...111 (0 followed by 63 bits of 1). Since you add a number to Long.MAX_VALUEyou will start receiving negative integers since the sign byte changes to 1. This means you have an numeric overflow, but this error isn't thrown by Java.

Java 不抛出异常并且您收到负数的原因与数字的存储方式有关。对于长原语,第一个字节用于指示数字的符号(0 -> 正,1 -> 负),而其余字节用于数字值。这意味着Long.MAX_VALUE最大的正值将存储为 01111...111(0 后跟 63 位的 1)。由于您添加了一个数字,Long.MAX_VALUE您将开始接收负整数,因为符号字节更改为 1。这意味着您有一个数字溢出,但 Java 不会抛出此错误。

回答by Davide Lorenzo MARINO

If the operation overflows, the results goes back to the minimum value and continues from there.

如果操作溢出,则结果返回到最小值并从那里继续。

There is no exception thrown.

没有抛出异常。

If your code can overflows you can use a BigIntegerinstead.

如果您的代码可能溢出,您可以使用 aBigInteger代替。

回答by Rafael Membrives

An extract from Mathjavadoc:

摘自Mathjavadoc

"The platform uses signed two's complement integer arithmetic with int and long primitive types. The developer should choose the primitive type to ensure that arithmetic operations consistently produce correct results, which in some cases means the operations will not overflow the range of values of the computation. The best practice is to choose the primitive type and algorithm to avoid overflow."

“平台使用int和long原始类型的有符号二进制补码整数算法。开发人员应选择原始类型以确保算术运算始终产生正确的结果,这在某些情况下意味着运算不会溢出计算值的范围. 最佳实践是选择原始类型和算法以避免溢出。”

For Java 8:

对于 Java 8:

"In cases where the size is int or long and overflow errors need to be detected, the methods addExact, subtractExact, multiplyExact, and toIntExact throw an ArithmeticException when the results overflow. For other arithmetic operations such as divide, absolute value, increment, decrement, and negation overflow occurs only with a specific minimum or maximum value and should be checked against the minimum or maximum as appropriate"

"在size为int或long需要检测溢出错误的情况下,addExact、subtractExact、multiplyExact和toIntExact方法在结果溢出时抛出ArithmeticException。对于除法、绝对值、递增、递减等其他算术运算,并且否定溢出仅发生在特定的最小值或最大值时,应根据需要检查最小值或最大值”