简体   繁体   English

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

[英]Java: Why does “long” number get negative?

I have this code: 我有这个代码:

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

Why does the long i get negative after a few prints? 为什么long i会在几次打印后变得消极? If the range is exceeded, shouldn't an error occur? 如果超出范围,是否应该发生错误?

Java doesn't throw an error if you increase a number after its maximum value. 如果在最大值之后增加一个数字,Java不会抛出错误。 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 ArithmeticException if you pass the Long.MAX_VALUE . 如果您希望出现此行为,可以使用Java 8中的Math.addExact(long x, long y)方法。如果传递Long.MAX_VALUE则此方法将抛出ArithmeticException

The reason why Java doesn't throw an exception and you receive negative numbers has to do with the way numbers are stored. Java没有抛出异常并且您收到负数的原因与数字的存储方式有关。 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. 对于长基元,第一个字节用于指示数字的符号(0 - >正,1 - >负),其余用于数值。 This means that Long.MAX_VALUE which is the biggest positive value will be stored as 01111...111 (0 followed by 63 bits of 1). 这意味着作为最大正值的Long.MAX_VALUE将被存储为01111 ... 111(0后跟63位为1)。 Since you add a number to Long.MAX_VALUE you 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. 由于您向Long.MAX_VALUE添加一个数字, Long.MAX_VALUE您将开始接收负整数,因为符号字节更改为1.这意味着您有一个数字溢出,但Java不会抛出此错误。

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 BigInteger instead. 如果您的代码可能溢出,则可以使用BigInteger

An extract from Math javadoc : Math javadoc的摘录:

"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" “在大小为int或long并且需要检测溢出错误的情况下,方法addExact,subtractExact,multiplyExact和toIntExact在结果溢出时抛出ArithmeticException。对于其他算术运算,例如除法,绝对值,增量,减量,并且只有特定的最小值或最大值才会出现否定溢出,并应根据需要检查最小值或最大值“

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM