Java 8无符号整数加法和潜在溢出

时间:2015-01-13 16:28:35

标签: numbers java-8 addition integer-overflow unsigned-integer

我正在使用Cay S. Horstmann的书“Java SE 8 for the Really Impatient”进行练习。其中一个基于Number类改进的练习要求:

  

编写一个添加,减去,除法和比较数字的程序   介于0和2之间 32 - 1,使用int值和无符号   操作。显示divideUnsignedremainderUnsigned的原因   必要的。

问题是,如果添加2个无符号整数,则总和可能溢出整数限制。如果不使用long存储总和并检查它是否大于Integer.MAX_VALUE,我没有看到防止这种情况的方法。是否可以仅使用整数执行此操作?

2 个答案:

答案 0 :(得分:5)

用于整数值的Two's complement具有整齐属性,无论您是将值解释为有符号还是无符号,都可以添加和减去它。

因此,即使在CPU级别,也没有用于添加/减去有符号或无符号数字的明确指令。这都是关于解释的。

因此,当您使用签名的int类型添加或减去两个无符号数字时,结果可能会在签名的int范围内溢出。但是当使用Integer.toUnsignedString打印现在为负数时,结果将是正确的无符号值,假设操作甚至没有在无符号整数值范围内溢出。

这就是为什么课程java.lang.Integer仅在必要时提供特殊的无符号操作,即用于比较两个无符号值,用于除法和余数以及来自和String(和long的转换,从longint的类型转换已经足够用于另一个方向。)

答案 1 :(得分:1)

为了获得unsigned int,您需要使用Integer.parseUnsignedInt()函数或进行手动计算。请记住,Java实际上并没有无符号整数,Java8只是提供了将int视为无符号的能力,以便允许更大范围的正数值。

根据Java 8 Doc for the Integer class

  

无符号整数映射通常与负值相关联的值   数字到正数大于MAX_VALUE

因此,无符号整数与有符号整数之间的转换是,如果该数字大于或等于零且小于或等于Integer.MAX_VALUE,则它保持不变。如果它大于Integer.MAX_VALUE但仍在无符号范围内,那么要将其存储在int中,您需要向其添加2 ^ 31,这会将其转换为正确的值,因为添加溢出被定义为操作的方式。除int等二进制原语外,溢出和下溢只会导致计数器重置并继续计数。

int min = Integer.MIN_VALUE;            // -2147483648
int max = Integer.MAX_VALUE;            // 2147483647
int overByOne = Integer.MAX_VALUE + 1;  // -2147483648 : same as Integer.MIN_VALUE
int underByOne = Integer.MIN_VALUE - 1; // 2147483647 : same as Integer.MAX_VALUE

他们练习只是要求你查看Integer类并测试各种(Java8中的新方法)无符号操作的方法。 Java没有无符号整数原语,但为了Integer类中的某些新方法,可以将int值视为unsigned。