3-整数运算

整数运算
Java的整数运算遵循四则运算规则,可以使用任意嵌套的小括号。四则运算规则和初等数学一致。例如:
        int i = (100 + 200) * (99 - 88); // 3300
        int n = 7 * (5 + (i - 9)); // 23072

但整数运算永远是精确的,即使是除法也是精确的,因为两个整数相除只能得到结果的整数部分
int x = 12345 / 67; // 184

注意:整数的除法对于除数为0时运行时将报错,但编译不会报错。

求余运算使用  %int y = 12345 % 67; // 12345÷67的余数是17

还有一种简写的运算符,即+=,-=,*=,/=,它们的使用方法如下:
int n += 100; // 相当于 n = n + 100;
int m -= 100; // 相当于 m = m - 100;


溢出
整数由于存在范围限制,如果计算结果超出了范围,就会产生溢出,而溢出不会出错,却会得到一个奇怪的结果:
        int x = 2147483640;
        int y = 15;
        int sum = x + y;// -2147483641

要解释上述结果,我们把整数2147483640和15换成二进制做加法:
 0111 1111 1111 1111 1111 1111 1000
+ 0000 0000 0000 0000 0000 0000 1111
------------------------------------
  1000 0000 0000 0000 0000 0000 0111

由于最高位计算结果为1,因此,加法结果变成了一个负数。
解决这个问题的方法也很简单,将 x 和 y 的类型 int 换成更大的 long 。

自增/自减
Java还提供了 ++ 运算和 -- 运算,它们可以对一个整数进行加1和减1的操作。
注意 ++/-- 写在前面和后面计算结果是不同的,++n 表示先加1再引用n,n++ 表示先引用n再加1。不建议把++运算混入到常规运算中,容易自己把自己搞懵了。
int age = 6;
//先自加,再使用(age先自加1,然后再打印age=7,此时age的值在内存中是7)
System.out.println("age=" + ++age);

//先使用,再自加
//此时age的值在内存中是7,先打印age=7,然后age再自加1,
//所以此时打印age=7,但是其实此时age的值在内存中已经是8了
System.out.println("age=" + age++);

//此时打印才是出来age=8
System.out.println("age=" + age);

int x = 100 + (++age);//不要这样用


移位运算
在计算机中,整数总是以二进制的形式表示。例如,int 类型的整数 7 使用 4字节 表示的二进制如下:
00000000 0000000 0000000 00000111
//左移
int n = 7;       // 00000000 00000000 00000000 00000111
int a = n << 1;  // 00000000 00000000 00000000 00001110 <= 14//左移1位 *2
int b = n << 2;  // 00000000 00000000 00000000 00011100 <= 28
int c = n << 28; // 01110000 00000000 00000000 00000000 <= 1879048192
int d = n << 29; // 11100000 00000000 00000000 00000000 <= -536870912
//左移29位时,由于最高位变成1,因此结果变成了负数。
//右移
int m = 7;       // 00000000 00000000 0000000 00000111
int x = m >> 1;  // 00000000 00000000 0000000 00000011 <= 3
int y = m >> 2;  // 00000000 00000000 0000000 00000001 <= 1
int z = m >> 3;  // 00000000 00000000 0000000 00000000 <= 0

如果对一个负数进行右移,最高位的 1 不动,结果仍然是一个负数:
int n = -536870912;
int a = n >> 1;  // 11110000 00000000 00000000 00000000 <= -268435456
int b = n >> 2;  // 10111000 00000000 00000000 00000000 <= -134217728
int c = n >> 28; // 10000000 00000000 00000000 00000001 <= -2
int d = n >> 29; // 10000000 00000000 00000000 00000000 <= -1

还有一种无符号的右移运算,使用>>>,也叫逻辑右移,若该数为正,则高位补0,而若该数为负数,则右移后高位同样补0:
int n = -536870912;
int a = n >>> 1;  // 01110000 00000000 00000000 00000000 <= 1879048192
int b = n >>> 2;  // 00111000 00000000 00000000 00000000 <= 939524096
int c = n >>> 29; // 00000000 00000000 00000000 00000111 <= 7
int d = n >>> 31; // 00000000 00000000 00000000 00000001 <= 1

注意:对 byteshort 类型进行移位时,会首先转换为 int 再进行位移。

位运算
位运算是按位进行与、或、非和异或的运算。
//与 有0出0,同1出1
n = 0 & 0; // 0
n = 0 & 1; // 0
n = 1 & 0; // 0
n = 1 & 1; // 1
//或 有1出1,同0出0
n = 0 | 0; // 0
n = 0 | 1; // 1
n = 1 | 0; // 1
n = 1 | 1; // 1
//非 0和1转换
n = ~0; // 1
n = ~1; // 0
//异或 相同为0,不同为1
n = 0 ^ 0; // 0
n = 0 ^ 1; // 1
n = 1 ^ 0; // 1
n = 1 ^ 1; // 0

对两个整数进行位运算,实际上就是按位对齐,然后依次对每一位进行运算。例如:
int i = 167776589; // 00001010 00000000 00010001 01001101
int n = 167776512; // 00001010 00000000 00010001 00000000
System.out.println(i & n);  // 167776512


运算优先级
在Java的计算表达式中,运算优先级从高到低依次是:
()
! ~ ++ --
* / %
+ -
<< >> >>>
&
|
+= -= *= /=


类型自动提升与强制转型
在运算过程中,如果参与运算的两个数类型不一致,那么计算结果为较大类型的整型。
例如,short 和int 计算,结果总是 int ,原因是 short 首先自动被转型为 intshort s = 1234;
        int i = 123456;
        int x = s + i; // s自动转型为int
        short y = s + i; // 编译错误!

将结果强制转型,即将大范围的整数转型为小范围的整数。强制转型使用(类型),例如,将int强制转型为 shortint i = 12345;
short s = (short) i; // 12345

注意:超出范围的强制转型会得到错误的结果,原因是转型时,int 的两个高位字节会直接被扔掉,仅保留了低位的两个字节:
        int i1 = 1234567;
        short s1 = (short) i1; // -10617
        int i2 = 12345678;
        short s2 = (short) i2; // 24910

猜你喜欢

转载自www.cnblogs.com/nsss/p/11417407.html