文章目录
- [%取余]
- [逻辑运算]
- [&位与运算]
- [|位或运算]
- [^异或运算]
- [~求反运算(位非运算)]
- [>>带符号右移位运算]
- [>>>不带符号右移位运算]
- [<<左移位运算]
- [++自增符号]
- [+=]
- [?:]
- [拓展:负数的二进制转换]
%取余
左操作数除以右操作数的余数
0%3 = 0
1%3 = 1
2%3 = 2
3%3 = 0
4%3 = 1
判断一个数是否能被另一个数整除,取余运算等于零即可
逻辑运算
&&
与运算:两侧同时为真才为真
只有true&&true
的情况下才为真
如果左侧为false
,右侧被忽略(短路与),也就是不会再判断第二个操作了
||
或运算:只要有一侧为真则为真
左侧运算完为true,右侧被忽略(短路或)
练习:输入年号判断是否是闰年
普通闰年:公历年份是4的倍数,且不是100的倍数的,为闰年(如2004年、2020年等就是闰年)。
世纪闰年:公历年份是整百数的,必须是400的倍数才是闰年(如1900年不是闰年,2000年是闰年)
将闰年的定义转变为程序,那么闰年的标准是:能被4整除,但不能被100整除;能被400整除
xml代码
<EditText
android:id="@+id/editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="输入年份"
android:inputType="textPersonName" />
<Button
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="doClick"
android:text="平年/闰年" />
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
java代码
public void doClick(View view) {
EditText et = findViewById(R.id.editText);
Button bt = findViewById(R.id.button);
TextView tv = findViewById(R.id.textView);
int year = Integer.parseInt(et.getText().toString());
if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {
tv.setText("闰年");
} else {
tv.setText("平年");
}
}
运行程序,结果如下:
&位与运算
运算规律如下:
0&0=0
0&1=0
1&0=0
1&1=1
5&3=1
5&3
的二进制运算过程
00000101
00000011 &
一一一一一一一
00000001
|位或运算
两个位只要有一个为1,那么结果就是1,否则就为0
5|1=5
5|1
的二进制运算过程如下:
00000101
00000001 |
一一一一一一一
00000101
^异或运算
两个操作数的位中,相同则结果为0,不同则结果为1,异或两次得到原值
5^1=4
的二进制运算过程如下:
00000101
00000001 ^
一一一一一一一
00000100
可以对布尔值异或,a^b,只有ab不同时才是真
~求反运算(位非运算)
如果位为0,求反结果是1,如果位为1,求反结果是0
~1=-2
的二进制运算过程如下:
00000001 ~
一一一一一一一
11111110
>>带符号右移位运算
将运算符左边的对象向右移动运算符右边指定的位数。使用符号扩展机制,也就是说,如果值为正,则在高位补0,如果值为负,则在高位补1.
5>>2=1
即 将5右移2位的二进制运算过程如下:
00000101 >>2
0000000101
一一一一一一一
00000001
多出来的右边2位舍弃,结果是1
>>>不带符号右移位运算
将运算符左边的对象向右移动运算符右边指定的位数。采用0扩展机制,也就是说,无论值的正负,都在高位补0.
5>>>2=1
运算过程和上边是一样的,其实正数右移 n 位,就相当于除上 2 的 n 次方的商,例如 5>>>2=1
即 5 ÷ 22 = 1
下面来看下-5>>>2=1073741822
的运算过程(如果不懂 -5 的二进制怎么转换,请看文章最后的拓展部分)
11111111111111111111111111111011 >>>2
0011111111111111111111111111111011
00111111111111111111111111111110 转换为十进制即为1073741822
<<左移位运算
思路和右移相同,不过是右侧补0
5<<2=20
0000 0101 <<2
0001 0100
0001 0100 转换为十进制即为20
其实,向左移 n 位,就相当于乘上 2 的 n 次方。因为如果我们从十进制来看移位运算:>>右移位1相当于除10,<<左移位1相当于乘10。同理那么二进制>>1相当于除2,<<1相当于乘2
练习:int拆分成4个byte整数
00000001 00000010 00000100 00001000
a b c d
思路:int 占 32 位,那么拆成 4 个 byte 整数,即每 8 位强转成 byte 即可
a右移24位,强制转型byte
b右移16位,强制转型byte
c右移8位,强制转型byte
d右移0位,强制转型byte
xml代码
<EditText
android:id="@+id/editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="输入整数"
android:inputType="textPersonName" />
<Button
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="doClick"
android:text="拆分/合并" />
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
java代码
public void doClick(View view) {
EditText et = findViewById(R.id.editText);
Button bt = findViewById(R.id.button);
TextView tv = findViewById(R.id.textView);
int a = Integer.parseInt(et.getText().toString());
byte b1 = (byte) (a >> 24);
byte b2 = (byte) (a >> 16);
byte b3 = (byte) (a >> 8);
byte b4 = (byte) (a >> 0);
tv.setText("" + b1);
tv.append("\n" + b2);
tv.append("\n" + b3);
tv.append("\n" + b4);
}
运行程序,结果如下:
练习:byte合并成int
思路:
00000001 a
10000010 b
10000100 c
10001000 d
最终结果为
00000001 10000010 00000100 00001000
A B C D
定义变量 r = 0
根据上一章的运算规则,byte运算会先转int
a转成int,符号位是0,所以左边补24个0
00000000 00000000 00000000 00000001
因为最终位置为A,所以左移24,然后和 r 求或运算
00000001 00000000 00000000 00000000
00000000 00000000 00000000 00000000 |
一一一一一一一一一一一一一一一一一一一一一一一一
00000001 00000000 00000000 00000000 重新赋值给 r
b转成int,符号位是1,所以左边补24个1
11111111 11111111 11111111 10000010
因为最终位置为B,所以左移16,然后和 r 求或运算
11111111 10000010 00000000 00000000
但是这样做以后,A位置就全变成了1,所以B应该先左移24位
10000010 00000000 00000000 00000000
然后再右移8位,然后再和 r 求或运算,这样做的目的是把符号消除掉
00000000 10000010 00000000 00000000
00000001 00000000 00000000 00000000
一一一一一一一一一一一一一一一一一一一一一一一一
00000001 10000010 00000000 00000000 重新赋值给r
c转成int,步骤同b,先右移>>24
11111111 11111111 11111111 10000100
再左移 <<24
10000100 00000000 00000000 00000000
>>>16和r求或
00000000 00000000 10000100 00000000
00000001 10000010 00000000 00000000 |
一一一一一一一一一一一一一一一一一一一一一一一一
00000001 10000010 10000100 00000000 重新赋值给 r
d转int,>>24
11111111 11111111 11111111 10001000
<<24
10001000 00000000 00000000 00000000
>>>24
00000000 00000000 00000000 10001000
00000001 10000010 10000100 00000000 |
一一一一一一一一一一一一一一一一一一一一一一一一
00000001 10000010 10000100 10001000 重新赋值给 r
在原来java代码后面增加
/*
**合并
* 1、定义变量r=0
* 2、b1左移24位,然后不带符号右移0位
* 与r求或,结果重新赋值给r
* 3、b2左移24位,然后不带符号右移8位
* 与r求或,结果重新赋值给r
* 4、b3左移24位,然后不带符号右移16位
* 与r求或,结果重新赋值给r
* 5、b4左移24位,然后不带符号右移24位
* 与r求或,结果重新赋值给r
*/
int r = 0;
r = r | (b1 << 24 >>> 0);
r = r | (b2 << 24 >>> 8);
r = r | (b3 << 24 >>> 16);
r = r | (b4 << 24 >>> 24);
tv.append("\n" + r);
运行程序,结果如下:
++自增符号
a++和++a 都属于自增运算符,区别是对变量a的值进行自增的时机不同。a++是先进行取值,后进行自增。++a是先进行自增,后进行取值
int a = 10;
System.out.println(a++);//输出10;a自增变成11,打印使用a的原值10;
System.out.println(a);//输出11;因为a已经自增变成11;
int a = 10;
System.out.println(++a);//输出11;a自增变成11,打印使用a自增后的11;
System.out.println(a);//输出11;a自增变成11;
int a = 10;
int b = a++;//给b赋a的原值,然后a自增1
System.out.println(b);//输出10
System.out.println(a);//输出11
int a = 10;
a = a++;//a自增为11;然后将a的原值重新赋值给a,所以a变回了原来的10
System.out.println(a);//输出10
最后一个稍微再解释下:首先 a++ 的取值结果为10, 然后 a 进行自增,此时 a=11 ,最后 进行赋值 ,所以 最后输出 a 的值 为 10.
+=
a+=b
,就是 a = a+b
常见的错误写法这里提一下:
byte a = 3;
a = a + 3;
这样写是错误的,a虽然是byte类型,但在运算的时候会自动转成int类型,所以 int类型加3 是一个int类型,再赋值给左侧的byte类型是错误的。所以必须这样写
a =(byte) a + 3;
也可以用以下写法,就省去了强转类型
a+=3;
?:
三元运算符(也叫三目运算符)经常用于取代某个类型的 if-then-else 语句,一般语法结构为:
result = <expression> ? <statement1> : <statement3>
expression 是一个布尔表达式。当 expression 为真时,执行 statement1, 否则就执行 statement3
练习:求最大值
xml代码
3个输入框+1个button按钮,并给button按钮增加doClick点击
java代码
public void doClick(View view) {
EditText et1 = findViewById(R.id.editText1);
EditText et2 = findViewById(R.id.editText2);
EditText et3 = findViewById(R.id.editText3);
Button bt = findViewById(R.id.button);
TextView tv = findViewById(R.id.textView);
int a = Integer.parseInt(et1.getText().toString());
int b = Integer.parseInt(et2.getText().toString());
int c = Integer.parseInt(et3.getText().toString());
int max = a > b ? a : b;
max = max > c ? max : c;
tv.setText("最大值是" + max);
}
运行程序,结果如下:
拓展:负数的二进制转换
我们来看下 -5 的二进制是怎么得到的:
首先 5 的二进制表示我们很熟悉了 0000 0101
接着得到反码,就是每位取反即:1111 1010
然后加1,得到补码,即:1111 1011
因为 int 占 32 位,所以我们写全即为11111111111111111111111111111011
因为之前我们算的都是正数,前边全是 0,不写全也没关系,不影响运算