第12章 整数运算

12.1 二进制补码运算
Java虚拟机所支持的所有的整数类型-byte, short、int和long,它们都是带符号的二进制补码数。二进制补码方案既能够描述正整数,也能够描述负整数。在一个二进制补码数中,最重要的位就是它的符号位。符号位为1,表示负整数;符号位为0,表示正整数和数字0。

能够被二进制补码方案表示的数的范围为:2的总位数次幂。例如,在Java中,short类型是16位带符号的二进制补码整数。能够惟一表示的整数数为:216或者65536。short类型值范围的一半被用来表示0和正整数,另一半被用来表示负数。16位二进制补码负数的范围是-32768 (0x8000)~-1(Oxffff),零用0x0000来表示,整数的范围是 1 (0x0001)-32 767 (0x7fff)。
正整数直觉上只不过是数的两种表示法之一。负数可以通过负数和2的某次方幂相加而得出。 例如,short类型的长度为16位,因此二进制补码表示法可以通过一个负数和2的16次幂(或者 65 536)的相加来得到一个有效范围内(-32 768 — 1 )的负数。-1的二进制补码表示为65 536 + (-1 )或者65 535 (Oxffff)。-2 的二进制补码表示为 65 536 + (-2 )或者65 534 ( Oxfffe )。

在带符号二进制补码数上进行的加法运算与在无符号二进制数上进行的加法运算一样。两个数相加(忽略溢出),结果被解释为一个带符号二进制补码数。这个过程将在运算结果是在该类型的有效范围内的情况下进行。例如,要获得4+ (-2 )的结果,只要把0x00000004和 Oxfffffffe相加即可。结果是Ox100000002,但是因为int类型只有32位,于是溢出部分被忽略,结果为0x00000002。

Java虚拟机中出现的整数运算的溢出并不会导致抛出异常,其结果只被简单地截短以符合数据类型(或者为int类型,或者为long类型)。例如,把int类型值0x7fffffff和1相加,将会得到 0x80000000。因此,如果相加值的类型为int而非long, Java虚拟机中2 147 483 647加上1的结果将会是-2 147 483 648。在Java中编程时,必须随时注意可能发生的溢出。必须在每一种情况下 确认所选择的数据类型(int或者long)是否正确。整数被0除时会抛出一个ArithmeticException 异常,所以应该时刻牢记此类异常将会被抛出,必须在必要的时候捕获异常。

如果long类型的长度仍然不能满足需要,可以使用java.math包中的Biglnteger类,这个类的实例可以描述任意长度的整数。Biglnteger类支持在任意长度整数上进行的所有数学运算,前提是这些运算是基于java虚拟机和java.lang.Math包所支持的基本类型的

12.3运算操作码
Java虚拟机提供几种进行整数算术运算的操作码,它们执行基于int和long类型的运算。如前所述,当byte、short和char类型值参与算术运算时,首先会将它们转换为int类型。对于每一个执行int类型算术运算的操作码,在long类型的相同运算中有对应的操作码。

整数加法可以在int和long类型上进行。表12-1描述了完成下列任务的操作码:弹出栈顶部的两个值,相加,把结果压入找。必须有指令先把两个相加的值压人栈。值的类型由操作码自己指定,最后得到的结果总是与相加的成员具有同样的类型。这些操作码都不会导致任何异常抛 出,溢出在这里通常被忽略。

前面我们得到了这样一条规则:运算操作码从栈中取出它们的操作数,但在表12-2中显示了 —个例外情况,即iinc操作码对int类型局部变量的加法操作。用于加法运算的局部变量位于字节码流中紧接于iinc指令之后的第一个字节,将要加到局部变量上的值从iinc指令之后的第二个字节取出。第二个字节被解释为一个8位的带符号二进制补码数。局部变量和8位带符号值相加, 相加的结果被写回局部变量。这条操作码可以用来给局部变量赋-128 ~ 127之间的值。这条操作码与用于控制循环(for或者while)执行的变量的加减相比,效率更高。与加法指令一样,这里没有任何异常抛出,溢出通常被忽咯。

表12-2的第二行说明了iinc指令的wide变量。如第10章中所述,通过使用wide指令,可以把无符号局部变量索引从8位扩展到16位。使用16位索引的指令可以对多达65536个位置的变量寻址。在iinc指令的处理过程中,wide指令也是用来把带符号的增量值从8位扩展到16位。因此, iinc操作码的wide变量可以在-32768 - 32767范围内改变一个局部变量的值。

值得注意的是,该字节码序列描述了在Java字节码的桟结构内处理java源代码中boolean类型 的方式。存储在位置2的局部变量中的值表示源代码中的boolean foundPrime变量,它是—个int 类型。它通过压人一个int常量为1或者0的指令设置为true或者false;通过执行int类型值与0进行 比较的指令来检查boolean类型的值。

猜你喜欢

转载自www.cnblogs.com/mongotea/p/11980070.html