我正在使用Cay S. Horstmann的书“Java SE 8 for the Really Impatient”进行练习。其中一个基于Number
类改进的练习要求:
编写一个添加,减去,除法和比较数字的程序 介于0和2之间 32 - 1,使用
int
值和无符号 操作。显示divideUnsigned
和remainderUnsigned
的原因 必要的。
问题是,如果添加2个无符号整数,则总和可能溢出整数限制。如果不使用long存储总和并检查它是否大于Integer.MAX_VALUE
,我没有看到防止这种情况的方法。是否可以仅使用整数执行此操作?
答案 0 :(得分:5)
用于整数值的Two's complement具有整齐属性,无论您是将值解释为有符号还是无符号,都可以添加和减去它。
因此,即使在CPU级别,也没有用于添加/减去有符号或无符号数字的明确指令。这都是关于解释的。
因此,当您使用签名的int
类型添加或减去两个无符号数字时,结果可能会在签名的int
范围内溢出。但是当使用Integer.toUnsignedString
打印现在为负数时,结果将是正确的无符号值,假设操作甚至没有在无符号整数值范围内溢出。
这就是为什么课程java.lang.Integer
仅在必要时提供特殊的无符号操作,即用于比较两个无符号值,用于除法和余数以及来自和String
(和long
的转换,从long
到int
的类型转换已经足够用于另一个方向。)
答案 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。