您的位置:首页 > 编程语言 > C语言/C++

黑马程序员——C语言基础篇---基本运算和位运算

2015-04-14 10:07 190 查看
------Java培训、Android培训、iOS培训、.Net培训期待与您交流! -------

前篇已经讲了一些基础语法,本篇来讲一下和计算相关的内容,主要包括基本运算和位运算。

一、基本运算

首先,我们要知道基本运算有哪些。

基本运算分为:算数运算、赋值运算、关系运算(比较运算)、逻辑运算,本小节会分三部分讲一下这些运算的使用以及在使用中需要注意的地方。

(1) 算数运算和赋值运算

算术运算符:+ 、- 、 * 、/、%

赋值运算符:= 、 += 、-= 、*=…

简单的不再多说,说一些需要注意的地方吧。

a. 自动类型转换和自动类型提升

请看下面一段代码,说出结果分别是多少。

int main()
{
int a = 10.6;

printf("%d\n",a);

int b = 10 +10.5;

printf("%d\n",b);

return 0;
}


结果公布:a的值是10,b的值是20。我们来看看这是什么原因。

a的值是因为自动类型转换,将右面的double型数据自动转换为int型,在赋值时,会自动将大类型转换为小类型,但是这回造成精度丢失,所以在写代码的时候一定要注意,要定义合适的数据类型。

那么b的值为什么是20呢?首先,(10 + 10.5)时,首先做了自动类型提升(在运算的时候),将10转成double型,与10.5做加法运算,然后将结果赋值给b(原理如a),结果就是20。

除法精度问题

下面这两句代码,输出的结果是多少?

double c = 1/2;
printf("%f\n",c);


可能大家的结果会是 0.500000,但实际结果是 0.000000

1和2都是int型的,在计算时其结果也是int型的,是0,尽管赋值给了浮点型的变量,也不能改变其结果,那如何才能输出正确的结果呢?
代码改成 double c = 1.0/2;(也可以用强制类型转换 double c = (double)1/2;)或double c = 1/2.0 既可,即除数和被除数至少有一个是double型的就可以了

b. 取余运算

现在通过一个小练习来引入取余

* 提示用户输入一个时间的秒数,比如500秒就输入500,然后输出对应的分钟和秒,比如500s就是8分钟20秒

代码如下:
int second = 0;
scanf("%d",&second);
printf("%d分%d秒\n",second/60,second % 60);
在计算秒数的时候,用了%来取余,也就是两个整数相除之后的余数。
取余有几点需要注意的地方

1)取余运算符左右两边都为整数,否则编译时会报错

2)取余结果的正负性只与%左边的数的正负性有关

printf("%d\n",(-32)%10);
printf("%d\n",32%(-10));
上面代码结果是 -2,而下面则是 2

c. 自增自减和复合赋值

int a = 10;
int a1 = 10;
int b = 10;
b += a++;
int c = 10;
c += ++a1;
printf("a = %d\na1 = %d\nb = %d\nc = %d\n",a,a1,b,c);


来看一下这一段代码,输出的结果为:

a = 11

a1 = 11

b = 20

c = 21
a因为a++,做了自加,值+1,结果是11;a1同样,由于++a,值+1,结果是11;
b += a++;这句话可以拆为

b = b + a;

a = a + 1;

也就是b先与a做加法,a的值再+1,b的值是20

c += ++a1;这句话可以拆为

a = a +1;

c = c + a;

a的值先+1,再与c做加法,c的值是21

(2) 关系运算和逻辑运算

关系运算符:(==、!=)(优先级相等)、(<、<=、>、>=)(优先级相等,且高于前者的优先级)
逻辑运算符:&&逻辑与、||逻辑或、!逻辑非

a.关系运算

关系运算符的结合方向为“从左往右”: 4>3>2

关系运算符的优先级小于算术运算符:3+4>8-2

通过下面这段代码来感受一下优先级吧

printf("%d\n",3 > 1 + 7);
printf("%d\n",(3 > 1) + 7);
printf("%d\n",5 != 4 + 2 * 7 > 3 == 1);


结果是:0 8 1

3 > 1 + 7 先算1+7 = 8,3>8的结果是0

(3 > 1) + 7 先算(3>1)结果是1,1+7=8

5 != 4 + 2 * 7 > 3 == 1 先算2*7=14,再算4+14 = 18,18>3的结果是1,5!=1的的结果是1,1==1的结果是1


b.逻辑运算

使用格式:条件A && 条件B、条件A||条件B、!条件A

逻辑与

只有当条件A和条件B都成立时,结果才为1,也就是“真”;其余情况的结果都为0,也就是“假”。因此,条件A或条件B只要有一个不成立,结果都为0,也就是“假”

举例说明:2 && 3 ,结果为1;2 && 0,结果为0;0 && 0,结果为0
逻辑或

当条件A或条件B只要有一个成立时(也包括条件A和条件B都成立),结果就为1,也就是“真”;只有当条件A和条件B都不成立时,结果才为0,也就是“假”。

举例说明:2 || 3 ,结果为1;2 || 0,结果为1;0 || 0,结果为0
逻辑非

对条件A进行取反

举例说明:!!!(10>4)结果为0

关于逻辑运算我觉得只有两点需要注意:
1.优先级

逻辑运算符的优先级顺序为:小括号() > 负号 - > ! > 算术运算符 > 关系运算符 > && > ||

2.&&和||是短路运算符

int a = 10;
int b = 20;
int c = (a > 11 && b++);
int d = (b || a--);
printf("a=%d\nb=%d\nc=%d\nd=%d\n",a,b,c,d);
结果为

a=10

b=20

c=0

d=1
int c = (a > 11 && b++);由于(a=10)>11的结果为0,短路运算,后面不再计算,所以b的值不变

int d = (b || a--);同理,a也不会进行运算了


(3) 三目运算

int a = 20;
int b = 21;
int c = a > b ? a : b;
printf("%d\n",c);


这是通过三目运算来找出两个数之间的最大值,结果21

int c = a > b ? a : b;可以拆分为

if (a >b)

{

c =a;

}

else

{

c=b;

}

二、位运算

位运算本来是应该在内存那里讲的,但是我自己在学习的时候比较容易把它与逻辑运算搞混,就在这里讲了。

1. & 按位与

只有对应的两个二进制位都为1,结果才为1,否则,结果为0作用:加密,获取精确的某一个二进制位
21 & 11的结果是多少?
首先转成二进制

21:10101

11:01011

---------------

& 00001

所以结果是1

由于任何二进制位与1进行按位与结果都是其本身,利用这一特性,可以获取一个数的二进制位(下面的代码)

int a = 0;
scanf("%d",&a);
int length = sizeof(a)<<2;
for (int i = length-1; i >= 0; i--)
{
printf("%d",((a>>i) & 1));
if (i % 4 == 0)
{
printf(" ");
}
}
printf("\n");


运行结果如下:

21

0000 0000 0001 0101

利用sizeof取出的是变量字节数,<<2相当于 *4(利用位运算效率更高),将变量从最高位开始取其二进制位与1进行按位与,就能求出其二进制

2. | 按位或

只要对应的二进制位有1位是1,那么结果就是1

21 | 11的结果是多少?

21:10101

11:01011

---------------

| 11111

转成十进制结果是31

3. ^ 按位异或

当两个二进制位相同时,结果为0;不相同时,结果为1

1. 相同数值进行异或,结果肯定是0
2. 异或的顺序可以交换,比如:9^5^9 = 9^9^5
3. 任何数值与0进行异或,结果还是原来的数值
4. a^b^a = b;

21 ^ 11的结果是多少?

21:10101
11:01011
---------------
^ 11110
转成十进制是30
异或还有一点小应用,那就是不利用第3方变量实现两个变量之间值得交换

a=a^b;

b=a^b;

a=a^b;

4. ~ 按位取反

不说了,就是取二进制位的相反值

5. << 左移

a<<n 例如:9<<2 9的二进制位向左移2位,最高2位舍弃,最低2位补0

a<<n
相当于a * 2的n次方

注意点:最高位舍弃,正负性可能改变

4. >>右移

a>>n 保持符号位不变,向右移n位
右移相当于a/2的n次方
关于计算的暂时就能想到这么多,你明白了吗?
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: