关系运算符和表达式
< > <= >= == != 关系运算符都是两目操作符
关系运算符的结果是逻辑值,真或者假 (C++里 true false)
==与=的区别,一个是关系运算判断是否相等,一个是赋值运算。
关系运算符的优先级比算术运算低,比逻辑运算(!逻辑非除外)高,==和!=比其他的低,结合方式从左到右。
C/C++里用1表示真,用0表示假,也就是说关系或者逻辑运算后的结果的真和假对应1和0。那么表示数学的区间【1,10】不能这样写: 1<=x<=10 因为按照语法从左到右,第一个的结果要么是0要么是1(真或假),肯定小于等于10,也就是不管x的值是什么结果都是真(1)!要解决这个问题需要通过逻辑运算
关系运算的左右两边都必须有意义并且可以比较大小的值,没有初始化的变量直接进行关系运算有可能出现错误:int x,y; x>y; (错)字符用ASCII码来比较大小。
判断两个浮点数是否相等或者不相等,应该尽量避免直接使用 == 或 != ,因为浮点数是有精度的,在精度范围外可能出现错误。
正确的方法是导入数学库 #include <math.h>或者C++的 #include <cmath> 调用绝对值函数来完成: fabs(x-y) < 1e-6 x和y的绝对值小于10的负6次方
单个关系运算表达式一般情况下是没有意义的: x > y ; x 和 y的值没有变化、结果也没有保存,初学者一般在分支结构的时候容易犯这样的错误! 在赋值、自增等特殊情况下,单个关系运算表达式还是有点作用的: x++ > y ; x的值发生了变化!
逻辑运算和表达式
&& 逻辑与 || 逻辑或 !逻辑非
逻辑非 ! 是单目运算,优先级非常高(比算法运算高,跟++ -- 都属于第2级)。逻辑与比逻辑或是双目运算,与比或高一级,但是比关系运算低(当然比算术运算更低)。
逻辑运算的操作数在实际意义上应该是逻辑值(也就是关系运算或者其他逻辑运算的结果),但是在C/C++中操作数不局限于逻辑值,更普遍的原则是操作数按照 ”非0即真“ 的方法来处理:
1 && 3 真 0 || x=1 真(后面表达式的值为1)
要和 关系运算中 的真假 用 1 和 0 来表示区分开来!
表示数学的区间可以用逻辑与来完成【1,10】===> x>=1 && x<= 10
多个逻辑运算连续使用要注意所谓的“熔断”机制,也就是结果一旦确定后面的运算表达式就省略掉了:
0 || x++> 5 这里x肯定会++ 1 || x++>5 则不会,因为结果已经显然不需要计算后面表达式
逻辑与也有这样的特点,要注意后面的赋值、复合赋值和自增自减运算!
算术运算中取余运算可以判断整除的关系,在关系和逻辑运算中经常用到,比如闰年的判断:
( year % 4 ==0 && year % 100 != 0) || (year % 400 ==0)
位运算
位运算的操作对象只能是整数或者字符类型
& 按位与 | 按位或 ^ 按位异或 ~ 按位取反 >> 左移 << 右移
~按位是单目运算,其他都是双目,优先级也最高(第2级);>> 左移 << 右移优先级低于算术运算高于关系运算。 & > ^ > | 这三个比关系运算低,比逻辑运算高。
位操作当然涉及到先进行二进制化处理:
补码:计算机中为了让加减统一操作(正数的减法可以看成是正数加一个负数),用补码来存储数值;原码、反码和补码正数都一样,对于负数反码就是将原码每位取反,补码则是取反再加1。
5 0000 0000 0000 0000 0000 0000 0000 0101 (32位 原码)
-5 (1)000 0000 0000 0000 0000 0000 0000 0101 (32位 原码)
-5 (1)111 1111 1111 1111 1111 1111 1111 1010 (32位 反码)
-5 (1)111 1111 1111 1111 1111 1111 1111 1011 (32位 补码)
负数原码到补码:取反+1(不包括符号位)。补码到原码可以 减1再取反 或者 再做一次求补运算(取反+1)
要注意,与取反求补的操作不同,位运算是包括符号位的!字符的位运算则是一个字节八位,区别上面整数的32位。
移位运算:左移一位在没有溢出(超过表示范围)的情况下等价于扩大该数两倍,右移则是缩小,相比除法运算,移位运算的效率高很多!
技巧:
1、二进制的权值从低到高: 1 2 4 8 16 ....可以进行组合来对指定的位进行处理;
2、按位异或 0 ( 0 ^ 0 ->0 1 ^ 0->1) 保持不变 , 1 ( 0 ^ 1 ->1 1 ^ 1->0) 取反 ; 32个1的二进制应该是 -1 ( 算下 -1 的补码)所以: 5 ^ -1 结果是 -6 (取反 );根据1可以针对特定位进行取反等操作(在控制系统中经常使用)
3、按位与 可以判断该数 指定位是否为1: x & 3 的结果可以 判断最低两位是否为1 ;判断x的奇偶性:x % 2 ==> x & 1 ; 判断某数的第K位是否为1 (x>>K) & 1 左移K位后判断最低位是否为1
4、按位或 可以把某位置 1 : x | 3 将最低两位设置成 1 ;同样可以把某数的第K位设置成1
5、按位运算可以和赋值组合起来成为复合赋值运算 x &= y ; x ^= y; x |=y; x<<=y; x>>=y;分解方法和前面的复合赋值运算一样
6、x &= (x-1) 的操作是将x的最低的第一个1设置成0 ,20的二进制有两个1,两次操作后变成0:
0000 0000 0000 0000 0000 0000 0001 0100 (20) 20 &= 19 结果是 16
0000 0000 0000 0000 0000 0000 0001 0000 (16) 16 &= 15 结果是0
while(x!=0){c++; &= (x-1);} 统计x的二进制有多少个1
条件和逗号表达式
条件运算符是唯一一个三目操作符,语法:
条件 ? 表达式1 : 表达式2 ;
条件为真,取表达式1做为条件表达式的值,否则取表达式2;
优先级低于逻辑运算高于赋值,结合方向从右到左:多个连续的条件表达式,从后到前进行组合。也就是说从右到左,冒号: 找它左边最近的 ? 结合(除非有括号)
逗号表达式优先级最低,语法
表达式1,表达式2....,表达式n ;
从左到右,依次计算,将最后一个表达式n的值做为整个逗号表达式的值。
条件和逗号表达式注意点:
1、计算时要注意赋值、复合赋值、前自增自减等运算符可能修改变量值;
2、关系和逻辑运算的特殊性,比如“熔断”机制。