C語言探索之旅 | 第一部分第七課:運算那點事

作者 謝恩銘,公眾號「程序員聯盟」(微信號:coderhub)。
轉載請注明出處。
原文:http://www.lxweimin.com/p/7bc4493ebb4f

《C語言探索之旅》全系列

內容簡介


  1. 前言
  2. 基礎運算
  3. 變量之間的運算
  4. 縮寫
  5. 數學庫
  6. 總結
  7. 第一部分第八課預告

1. 前言


上一課是 C語言探索之旅 | 第一部分第六課:變量的世界(三),顯示變量內容

今天,我們一起來學習 C語言(對大多數編程語言也類似)中的運算。

之前的課中,我們已經說過:電腦是一臺“笨笨”的機器,只會做計算。

不管你是用電腦來聽音樂,還是用電腦來看電影,玩游戲,其實電腦只是在做運算。不然怎么叫“計算機”呢?

這一課我們一起來學習電腦能實現的大多數運算。我們會繼續使用上一課學到的變量的知識。其實,就是對變量做加,減,乘,除,取模,等等各種操作。

即使你對數學不感興趣,這一課也是必不可少的。硬著頭皮上吧~

2. 基礎運算


說到基礎運算,無外乎:

  • 取模 (如果你是第一次聽說,不用擔心,我們后面會解釋)

其實你的電腦也只知道做這些基礎運算,如果你要它做更復雜的運算(平方,乘方,對數,等),那你需要編程才行,就是說你需要向電腦解釋怎么做。

但是,很幸運的是,在這一課中我們會看到其實 C語言已經設計好了數學庫(關于庫的知識,請看以前的課程。簡單地說就是已經編寫好的,可以供你的程序調用的各種變量和函數的集合),你只要用專家定義好的庫里面的內容就好了,不需要自己重復“造輪子”。

一開始,我們從加法開始看吧。

為了在 C語言中做加法,我們要用到 + 號。不開玩笑,就是這么簡單。

你要把加法的結果放到一個變量里面。我們就來創建一個整數類型的變量,取名叫 result(表示“結果”)。

int result = 0;
result = 4 + 6;

不必是專業數學家,也可以猜想到程序運行后 result 的值會變為 10,我們用 printf 函數來輸出結果:

printf("4 + 6 = %d", result);

運行程序,顯示:

4 + 6 = 10

看吧,加法就是這么簡單,一點也不任性。

對于其他的運算類型,也是同樣的原理。只有運算符不同,見下表:

運算 符號
加法 +
減法 -
乘法 *
除法 /
取模 %

如果你曾經使用過電腦上的計算器,你肯定知道這些符號。除了最后兩個(除和取模),其他應該很熟悉。我們就來說說最后兩個符號。

除法


當沒有余數時,除法運行得好好的。比如,6 / 3 等于 2,你的電腦給了你正確的答案。到這里為止還沒有問題。

但是,我們假如讓電腦做 5 / 2,按理結果應該是 2.5。但是,來看看我們的程序:

int result = 0; 
result = 5 / 2;
printf ("5 / 2 = %d", result);

運行程序,顯示:

5 / 2 = 2

我們讓電腦計算 5 / 2,期待的結果是 2.5,但是實際上電腦卻給出了 2。這不是“很二”嘛... 親愛的電腦,你怎么可以這樣對我?

其實,內有蹊蹺。難道我們的電腦真的在這點上這么蠢笨嗎?

事實上,當電腦看到數字 5 和 2 時,它會做一個整數之間的除法(也叫做“歐幾里得除法”),就是說它會把結果截取一段,只留下整數部分(這里是 2)。

你也許會說:“啊,我知道了,都是因為 result 這個變量是整數類型嘛。如果把 result 聲明為 double 類型的浮點數,那它應該可以儲存帶小數點的數啦。”

其實不然,這不是原因。假如你把 result 聲明為 double 類型,運算
result = 5 / 2,你還是會得到 2。事實上,這是因為 / 運算符兩邊的數是整數,所以電腦會做整數之間的除法。

當然,也是可以讓電腦輸出你想要的結果的,怎么辦呢?看下面程序:

double result = 0; 
result = 5.0 / 2.0;
printf ("5 / 2 = %f", result);

運行,顯示:

5 / 2 = 2.500000

看到了嗎,如果要你的電腦顯示正確結果,還需要你把運算符兩邊的數寫成 5.0 和 2.0(同樣是 5 和 2,但是電腦卻認為這兩個是浮點數,因此它就做浮點數的除法)。怎么樣,電腦任性不?

這個整數除法的特性很重要。所以得記住,對于電腦來說:

5 / 2 = 2

10 / 3 = 3

4 / 5 = 0

有點令人吃驚,不是么?但這就是電腦做整數運算的方式。

如果你想要得到浮點數的結果,需要運算的數本身是浮點數(提一下,其實不需要兩個數都是浮點數,一個是浮點數就夠了,電腦會自動把另一個也認為是浮點數來做運算):

5.0 / 2.0 = 2.5

10 / 3.0 = 3.33333

4.0 / 5 = 0.8

事實上,在做整數除法時,比如 5 / 2,你的電腦會回答下面問題:“5里面有多少個 2 ?”,答案是兩個。同樣的,“10 里面有多少個 3 呢”,答案是三個。

然后你又會問了,我們怎么才能獲取到除法剩下的數(余數)呢?

這就要輪到取模運算出場了。

取模


取模運算是獲得除法的余數的一種數學運算。可能相比 加、減、乘、除這基本的四則運算來說,它沒有那么被人熟知,但對電腦來說,取模是基本的運算之一。很有可能是為了解決上面提到的整數除法的難題。

上面表格里列出來了,取模的符號是 %

以下列出一些取模運算的例子:

5 % 2 = 1

14 % 3 = 2

4 % 2 = 0

取模運算 5 % 2 是除法運算 5 / 2 的余數,所以是 1。電腦計算 5 = 2 * 2 + 1,所以取模運算就得出 1 為結果。

同樣地,14 = 3 * 4 + 2,所以余數為 2。

4 = 2 * 2,所以余數為 0。

好了,我宣布一個好消息:“我們已經學了所有的基礎運算了。數學課下課了~”

3. 變量之間的運算


誒,變量之間的運算?

怎么數學老師剛走,又來了數學教授啊?沒辦法,電腦又名計算機,肯定要跟數學打點交道的嘛。幸虧來的不是“叫獸”。

既然我們在上面一節中已經學習了基礎的 5 種運算,那現在可以來看看變量之間的運算咯。

事實上,變量之間的運算也是同理。

result = number1 + number2;

上面這一行代碼對 number1 和 number2 這兩個變量做加法運算,并且把結果儲存到 result 這個變量里。

現在我們的學習越來越有意思了。其實你現在已經可以實現一個迷你的計算器的功能了,不要懷疑自己,你可以的。

想象一個程序,請求用戶輸入兩個數,這兩個數,你將其儲存在變量里。

然后,你對這兩個變量做加法,并且把結果儲存在另一個變量里。接下來,你就只需要把計算的結果顯示在屏幕上就好了,讓用戶看看電腦的本領,很多人做加法可沒有這么快速呢!

試著自己編寫以上程序,很簡單的,也可以給你練手。

當然了,我們還是把代碼寫上:

#include <stdio.h>

int main(int argc, char *argv[])
{
    int result = 0, number1 = 0, number2 = 0;

    // 請求用戶輸入number1和number2的值:
    printf("請輸入數字1 : ");
    scanf("%d", &number1);
    printf("請輸入數字2 : ");
    scanf("%d", &number2);

    // 做運算:
    result = number1 + number2;

    // 把運算結果顯示在屏幕上 :
    printf ("%d + %d = %d\n", number1, number2, result);

    return 0;
}

運行,顯示:

請輸入數字1 : 289
請輸入數字2 : 376
289 + 376 = 665

可能你還沒意識到:這是我們第一個有點意思的程序。我們的程序請求用戶輸入兩個數,然后做加法,再把結果輸出到屏幕上。很棒吧!

請你自己也試著用其他四個基礎運算符來寫程序,看看結果如何。

4. 縮寫


之前我們保證過,不會再有新的運算形式出現了。確實如此,我們已經知道了所有的基礎運算:加、減、乘、除、取模。用這些基礎運算我們可以做所有事情。不需要其他的運算了。

我知道這很難令人相信。你會說難道一個很復雜的 3D 游戲最終也是由加、減、乘、除等構成的?是的,確實如此。

雖然如此,但是在 C語言里我們還可以進行運算的縮寫。

為什么要縮寫呢?因為很多時候我們做的運算都是重復的。下面你就會看到縮寫的好處了。

自增運算


你會發現你在編程中經常要對一個變量進行 +1 操作。

假設你的變量名字是 number,你知道怎么對它進行 +1 操作嗎?是這樣做的:

number = number + 1;

上面的語句做了什么呢?

首先我們做運算 number + 1,然后我們把運算結果儲存到變量 number (它自己)中。

因此,假如我們的變量值是 4,運算后變成 5 了,假如它的值是 8,那會變成 9,依此類推。

這個運算是重復的。要知道,計算機科學家都是很懶的人,他們可不希望輸入兩遍 number(確實也挺累人的)。

于是他們發明了一個縮寫形式,叫做自增運算。它的結果和 +1 操作是一樣的:

number++;

這一行代碼,就是用了自增運算符 ++,是不是比剛才那句 number = number + 1 簡單了?它意味著“對 number 做 +1 運算”。

敏銳的讀者可能想到了,編程語言 C++ 的 ++ 符號其實正是自增運算符的意思。我以前也不太理解為什么不是 C+,而是 C++。

原來計算機科學家跟大家開了一個很有意味的玩笑:C++ 意味著對 C 做 +1 操作,表示“比 C語言多一點”。

當然了,事實上 C++ 只是用不同的方式來編程,并不是說 C++ 比 C語言更優秀,只是不同而已。

自減運算


知道了自加運算的原理,自減運算應該不難理解吧:就是對變量進行 -1 運算。

number--;

其他的縮寫形式


同理,其他還有好幾種運算的縮寫形式。比如 number = number * 2; 可以寫成 number *= 2;

看以下代碼:

int number = 2;

number += 4;  // number 變為 6
number -= 3;  // number 變為 3
number *= 5;  // number 變為 15
number /= 3;  // number 變為 5
number %= 3;  // number 變為 2(因為 5 = 1 * 3 + 2)

5. 數學庫


在 C語言中,我們有一些稱之為“標準庫”的東西,就是那些很實用的庫。我們一般會經常使用那些基礎庫。

復習一下:庫就是指已經定義好的函數和變量的集合。這些函數由前人寫成,可以避免我們重復“造輪子”。

我們已經使用過 stdio.h 庫中的 printf 和 scanf 這兩個函數了。

其實還有很多其他很實用的庫,其中就有一個叫 math.h,里面包含了與數學相關的函數。

實際上,光是加、減、乘、除、取模是不夠的。雖然底層都是這五個運算,但是很多時候我們需要做復雜的運算形式,就需要調用庫或者自己寫函數了。

因為電腦并沒辦法理解除了 +,-,*,/,% 之外的運算符,比如你如果要電腦做乘方,輸入 5 ^ 2,電腦完全不理解什么意思,除非你調用數學庫里已經定義好的做乘方的函數。

調用數學庫很簡單,

#include <math.h>

只要用這一行代碼,接下來你的程序就可以用里面定義的所有函數了。

我們介紹其中幾個最常用的吧。

fabs


這個函數返回絕對值:

  • 如果你傳給這個函數 -53,它會返回 53 。
  • 如果你傳給這個函數 53,它會返回 53 。
double absolute = 0, number = -29;
absolute = fabs(number);   // absolute 的值變為 29

ceil


這個函數返回給出的浮點數后面緊接的整數。這是一種舍入的方式。ceil 函數總是舍入緊鄰的比參數大的整數。

double above = 0, number = 34.81;
above = ceil(number);  // above 的值變為 35

floor


這個函數與 ceil 的作用相對,返回給出的浮點數前面緊接的整數。

double below = 0, number = 45.63;
below = floor(number);   // below 的值變為 45

pow


這個函數計算數字的乘方。你要給它兩個參數:底數和指數。

double result = 0, number = 2;
result = pow(number, 4);  // result 的值變為 16(2 ^ 4 = 16)

sqrt


這個函數返回參數的平方根。返回值是 double 類型。

double result = 0, number = 100;
result = sqrt(number);  // result 的值變為 10

sin, cos, tan


這三個函數是計算正弦,余弦,正切的值。

asin, acos, atan


這三個函數是計算反正弦,反余弦,反正切的值。

exp


這個函數是特殊的乘方形式,返回以 e(自然對數的底數,近似等于2.7182)為底數的指數運算的值。

log


這個函數返回以 e 為底的對數值(我們學數學時也寫成 ln)。

log10


這個函數返回以 10 為底的對數值。

6. 總結


  1. 電腦只知道計算。

  2. 電腦會的運算類型很基本:加、減、乘、除、取模(取模就是做除法后剩下的部分)。

  3. 自加是將變量加一的運算,寫成 variable++ 。

  4. 自減是將變量減一的運算,寫成 variable-- 。

  5. 為了增加電腦能知道的運算形式,需要載入數學庫(#include <math.h>)。

  6. 數學庫里有更高級的函數,例如 乘方,平方根,舍入,指數,對數,等。

7. 第一部分第八課預告


今天的課就到這里,一起加油吧!

下一課:C語言探索之旅 | 第一部分第八課:條件表達式


我是 謝恩銘,公眾號「程序員聯盟」(微信號:coderhub)運營者,慕課網精英講師 Oscar 老師,終生學習者。
熱愛生活,喜歡游泳,略懂烹飪。
人生格言:「向著標桿直跑」

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,546評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,570評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,505評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,017評論 1 313
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,786評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,219評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,287評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,438評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,971評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,796評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,995評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,540評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,230評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,662評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,918評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,697評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,991評論 2 374

推薦閱讀更多精彩內容