10-15日(第七週週一)上課簡記
計算機歸根結底所做的事情只有一件,就是計算。而最簡單的計算就是算術運算。我們上小學就開始接觸算術運算。
1.算術運算子及表示式
1.1 常用的演算法運算子有:加“+”,減“-”,乘“*”,除“/”和取餘“%”。
#include<stdio.h> int main() { int i=24,j=7,k; double t=3.0,m; k=i+j; m=i+j; printf("k=%d,m=%lf\n",k,m); k=i/j; m=i/j; printf("k=%d,m=%lf\n",k,m); m=24/3.0; printf("m=%lf\n",m); return 0; }
C語言規定:參與運算的資料均為整型時,結果為整型。例如:k=i+j; k=i/j;
C語言規定:參與運算的資料中有一個數為實型,則結果為double。
例如:m=i/t;t為double型別,所以i/t的值也為double型別。將該值賦給double型別的m,資料不會丟失。
1.2 取餘(或求餘)運算子:%
含義:**a%b,求的是a與b相除之後的餘數。**也稱a對b求餘,或a對b取模。
#include<stdio.h> int main() { int i=24,j=7,k,m; k=i%j; m=i%3.0; printf("k=%d,m=%d\n",k,m); k=(-i)/j; m=(-i)%j; printf("k=%d,m=%d\n",k,m); k=i/(-j); m=i%(-j); printf("k=%d,m=%d\n",k,m)); return 0; }
執行上述程式,編譯器提示什麼錯誤?如果修改程式?
C語言規定:參加求餘的兩個運算元必須是整型。
例項:輸出一個三位整數的個位、十位和百位數字。
關鍵:如何分離出個位、十位和百位數字?
思路:153/100=1得到的結果就是百位。153%10=3得到個位。
153-1*100=53,這樣十位就是最高位,繼續53/10=5得到。
另一種:153%100=53,53/10=5
問題:求餘運算還有什麼用?
C語言的隨機函式rand()可以生成一個在0至32767之間的隨機數,如果我們想生成一個指定範圍(如1~100)內的隨機數呢?
可以對:magic=rand()%100; //0~99
magic=rand()%100+1就可以生成1~100之間
生活中的求餘運算例子
一天是24小時,我們說幾點了,就是對24取餘得到的。 此外,取餘還能判斷某數是否能被整除。
如何進行更復雜的數學運算呢?
常用的標準數學函式:
函式名 功能
exp(x) e的x次方
pow(x,y) x的y次方
sqrt(x) x的平方根(x>=0)
fabs(x) X的絕對值
log(x) Inx,(x>0)
sin(x) sinx,x為弧度值
使用這些函式時,需要在程式開頭加上:#include<math.h>
1.3自加和自減運算子
#include<stdio.h>
int main()
{
int i=24,j=7;
i++;
j--;
printf("i=%d,j=%d\n",i,j);
i=24;j=7;
++i;
--j;
printf("i=%d,j=%d\n",i,j);
return 0;
}
執行該程式,看看兩條輸出語句輸出的結果是什麼?結果一樣嗎?
自加運算子:++。使變數的值加1之後重新寫回到變數中。
自減運算子:- -。使變數的值減1之後重新寫回到變數中。
運算元只能是變數,也稱為自增運算子或自減運算子。
字首:++n等價於n=n+1; --n等價於n=n-1
字尾:n++等價於n=n+1; n–等價於n=n-1
思考:增1運算子無論是作為字首還是字尾,其作用均讓變數增1,那為何還要區分字首和字尾呢?
#include<stdio.h>
int main()
{
int i=24,j=24,m,n;
m=i++;
n=++j;
printf("m=%d,n=%d\n",m,n);
printf("i=%d,j=%d\n",i,j);
i=24;j=24;
printf("%d,%d\n",--i,j--);
printf("%d,%d\n",i,j);
return 0;
}
執行上述程式,分析執行結果。
作為字首時:先對n增1或減1,然後再使用n的值。例如:n=++j; 等價於:j=j+1;n=j; 對於大多數編譯器來說,採用自增運算子程式執行效率較高。例如:printf(“%d”,–i);
作為字尾時,先使用n的值,然後再對n增1或減1。例如:m=i++; 等價於:m=i;i=i+1; 對於大多數編譯器來說,採用自增運算子程式執行效率較高。例如:printf(“%d”,j–);
又比如: printf(“%d”,-(n++));等價於 printf(“%d”,-n); n=n+1;
**注意:**增1和減1運算生成的程式碼效率更高一些。但是過多的增1和減1運算混合的話就會產生副作用,例如:m=(++n)+(n++)程式的可讀性變差,很難分析出來n的變化規律,此外不同的編譯器產生的執行結果是不同的。
良好的程式設計風格提倡:在一行語句中,一個變數最多隻出現一次增1或減1運算
3.賦值運算子及表示式
#include<stdio.h>
int main()
{
int i=24,j,m;
j=m=4;
i=i+3;
j+=4;
printf("i=%d,j=%d\n",i,j);
m+=m-=m*m;
printf("m=%d",m);
return 0;
}
執行程式,分析結果。弄明白語句:j=m=4;j+=4; m+=m-=m*m;的含義是什麼?
前面我們說過,int a;這條語句的意思是聲明瞭一個整型變數a。
通過a=3; 這條語句可以給a賦值。“=”就是賦值運算子,看上去和數學中的等號相同,在數學裡面:a=3的意思是a的值是3,a的值和3是相等的。但在c 語言中,賦值運算子是有方向性的,表示將3賦值給a。
簡單賦值:變數=表示式;例如int a; a=3;
多重賦值:變數=變數=表示式;
例如:int a,b; a=b=3;賦值運算子的結合性是右結合性,相當於a=(b=3),先執行b=3,再執行把表示式b=3的值賦值給a.
思考:a=a+10;從數學上看,這個表示式是錯誤的。但在C語言中,是將a+10的值賦給a。相當於對右側的a執行讀操作,對左側的a執行寫操作。可以寫成a+=10;+=是複合賦值運算子。
例如:a-=3;等價於a=a-3;
初始化:int a=3;等價於int a;a=3;
前面提到:a=b=3;但不可以int a=b=3; 可以寫成:int a=3,b=3;
4.關係運算符及其表示式
關係運算符用來比較兩個量的大小關係。C 語言提供的關係運算符有:<,<=,>,>=,==,!=。關係表示式的值是邏輯值:真或假,在程式中用1表示真,用0表示假。
關係運算符都是雙目運算子,結合性均為左結合性。
例如:8<2>5;先計算8<2,結果為0,再計算0>5,關係表示式的值為0。
#include<stdio.h>
int main()
{
int i=24,j=7,m;
m=24>7;
printf("(1)m=%d\n",m);
m=24>7>3;
printf("(2)m=%d\n",m);
m=24>7<=8;
printf("(3)m=%d\n",m);
m=(i==j);
printf("(4)m=%d\n",m);
m=i!=j;
printf("(5)m=%d\n",m);
return 0;
}
執行程式,看看輸出結果。
分析下面程式;
#include<stdio.h>
int main()
{
double i=24,j=7,k,m;
k=i/j*j;
if(i==k)
printf("i is equal k\n");
/* if(fabs(i-k)<1e-6)
printf("i is equal k\n");*/
return 0;
}
思考:實數如何進行相等或不等的判斷???
下列程式的功能是判斷i和j是否相等。對否???
#include<stdio.h>
int main()
{
int i=24,j=7;
if(i=j)
printf("i is equal j\n");
else
printf("i is not equal j\n");
return 0;
}
5. 邏輯運算子
邏輯運算子用於邏輯運算,運算子有三個:!邏輯非,&&邏輯與,||邏輯或。C語言沒有邏輯型別資料,當進行邏輯判斷時,如果資料的值為0,則認為邏輯假,如果資料的值為1,則認為邏輯真。同理,邏輯表示式的值為真時,用1表示,反之用0表示。
#include<stdio.h>
int main()
{
int i=24,j=7,m;
m=i&&j;
printf("(1)=%d\n",m);
m=i||j;
printf("(2)=%d\n",m);
m=!i;
printf("(3)=%d\n",m);
return 0;
}
執行程式,觀察m的值??把i和j的值改變一下,再看看程式執行結果??
思考:在現實生活中,經常會出現閏年,所謂的閏年就是為了彌補因人為曆法規定造成的年度天數與地球實際公轉週期的時間差而設立的。接下來編寫一個程式,使用邏輯運算子與if語句判斷年份是閏年還是平年。
閏年:輸入年號,能被400整除,則是閏年;如果能被4整除,而不能被100整除,則是閏年;其他情況均不是閏年。
#include<stdio.h>
int main()
{
int year,flag;
printf("please input year:");
scanf("%d",&year);
if(year%400==0)
flag=1;
else
{
if(year%4==0&&year%100!=0)
flag=1;
else
flag=0;
}
if(flag==1)
printf("%d is a leap year!\n");
else
printf("%d is not a leap year!\n");
return 0;
}
這個程式將算術運算子、關係運算符、賦值運算子、邏輯運算子均運用到了。
6.條件運算子(唯一的一個三目運算子)
例如:要判斷兩個整型的大小,輸出較大者。
#include<stdio.h>
int main()
{
int a,b,max;
printf("please input a,b:");
scanf("%d%d",&a,&b);
max=a>b?a:b;
printf("max=%d\n",max);
return 0;
}
其實,該程式可以有很多種實現方法。
7.sizeof運算子
該運算子用於測試資料型別所佔的位元組數。
#include<stdio.h>
int main()
{
int a=45;
printf("%d\n",sizeof(a));
printf("%d\n",sizeof(int));
printf("%d\n",sizeof(45));
return 0;
}
均輸出了int型所佔的記憶體位元組數。
8.混合運算時資料型別的轉換
8.1 系統自動進行型別轉換(隱式轉換)
算術表示式中,相同型別資料的運算結果的型別還是該型別。不同型別資料的運算結果的型別是:取值範圍較大的那種型別。
C99標準:long double<—double<—float<—unsigned long<—long<—unsigned int<—int
而char 和short在進行混合運算時均先轉為int。
int +float-——>float+float。編譯器把int型直接轉換為float,就可以參與運算了。
特例:long+unsigned int
long型別表達的資料的上限值為2147483647,而unsigned int表達的資料的上限值為4294967295,如果把unsigned int 轉換為long,可能會造成溢位,因此編譯器會將二者均轉換為unsigned long,然後進行運算。
設計轉換規則是因為高級別的型別所佔的位元組數大,可以避免在運算過程中造成資料的丟失。
8.2 型別顯式轉換
有時這種隱式的自動型別轉換,可能不是程式設計師的本意,如何顯式地表明程式設計師的意圖呢?
可採用顯式轉換,也稱為強制轉換。
#include<stdio.h>
int main()
{
int total=15,number=2;
float aver;
aver=(float)total/number;
printf("(1)%f\n",aver);
aver=(float)(total/number);
printf("(2)%f\n",aver);
return 0;
}
執行程式,分析結果。