1. 程式人生 > 其它 >【C++教程】04.求1加到100

【C++教程】04.求1加到100

技術標籤:# C++教程c++

第四章求1加到100

前言

該問題就是求1加2,再加3,一直加到100的值。此章我們用程式碼來實現一下,並介紹用到的C++語法知識。

1.神童高斯

1786年,高斯9歲的時候,由於他老師想打發一下上課時間,於是讓學生們計算1加到100的結果,他心想必然不太可能這麼快算出來,結果高斯用了不同於硬算的方法很快得出了結果。就在前不久我那讀初一的妹妹給我說到有次捱打就是因為求這個問題,我心裡一驚我小時候也應為這個問題被我爸打過。所以有些結論現代人看上去很簡單,在以前的時代其實並不是那麼容易得出的,並不是以前的人比現代人笨,而是現代人站在了巨人的肩膀上,在一些事情上,經典或許比潮流更有價值。

2.控制結構

計算機天生適合做重複性勞動,現在的CPU可以一秒鐘計算幾十億次加法,所以我們依次加對應的值計算就可以了。在進入主函式後,程式依次往後執行。但程式語言可以通過迴圈結構反覆的執行一段程式碼;又或是判斷條件,選擇執行某一部分的程式碼,這個叫選擇結構;直接結束函式的執行,跳轉到某一程式碼位置,這個叫跳轉語句;以上都被稱為控制結構,也就是控制程式執行的順序。

在這個求和問題中,我們可以通過迴圈執行加法,從而計算出結果。而最簡單的迴圈結構是通過while關鍵字來實現的,如下:

while(條件)
{
    //執行內容
}

//條件為假時才會跳出迴圈,接著執行這裡的語句

3.int型別

int型別是一種基本資料型別

,用來表示整數。在32位和64位程式中,都是32位大小,也就是在記憶體中需要32位二進位制來表示它,也就是4個位元組。我們在程式碼中定義一個int型變數,用於儲存整數,程式在執行時,就會在記憶體中佔用4個位元組的空間。我們可以計算一下4G的記憶體條可以儲存多少個int型變數:

4G記憶體換算為位元組:4GB = 4*1024MB=4*1024^2KB=4*1024^3byte

所以是1024的3次方個,也就是大概10億個。

然後int型別可以表示多少個值呢?也就是2^32,等於4294967296。雖然43億是一個很大的數字,但是隨便在紙上多寫幾位就超過了,在處理更大的數字時,就不能使用int型別了。不過只要計算的數字不會太大,就可以暫時不用考慮這個問題。

int型別是可以表示負數的,所以它的實際取值範圍為[-2147483648,2147483647]。當然這是整數,二進位制的值本身就是整數,是離散的。如果要表示小數,則是使用其他的基本資料型別,例如float、double,但是它們是不精確的,以後再完整的講解所有的基礎型別。

在本章中,使用int型別就夠了。在前面的章節中也出現了int型別的身影,如果我們要定義一個int型別的變數,來儲存計算的結果,就如下寫:

int count = 0;//定義了一個int型變數,名字為count,初始值為0

我們還需要一個累加的變數,來表示1到100:

int add = 1;//定義了一個int型變數,名字為add,初始值為1

4.編寫程式碼

首先先定義主函式,可以注意到主函式的返回值也是int型別,然後通過return語句返回了0:

int main()
{
    return 0;
}

接著定義所需的變數,來表示一個值:

int main()
{
    int count = 0;//累加結果
    int add = 1;//單個值,一開始加的是1

    return 0;
}

迴圈的進行加法計算,將add的值加到count上,然後每次迴圈add還需要加1,這樣99次迴圈後,add就從1變化到了100。當迴圈第100次時,add大於100,不滿足條件,所以結束迴圈執行while花括號括起來外面之後的語句,也就是return 0;退出了主函式,即將結束程式執行:

int main()
{
    int count = 0;//累加結果
    int add = 1;//單個值,一開始加的是1

    while(add <= 100)//大於100時就不迴圈了(等於100時還需迴圈)
    {
        count = count + add;//count加上add的值
        add = add + 1;//add每次迴圈加1
    }
    return 0;
}

雖然求得了1加到100的值,儲存到了count變數裡,但還需要用標準庫的iostream輸出列印到控制檯,不過在這之前可以用編譯器的斷點除錯功能,檢視各個變數的值,在下圖return 0;結束整個程式之前那一行程式碼的左側點選一下,就可以新增一個斷點:

當程式執行到此處時就會中斷,並且在下方的視窗可以看到變數的值:

再點綠色按鈕繼續,就可以繼續程式的執行,這時就會主函式返回,從而結束整個程式。

最後按照第三章的輸出方法,打印出count的值,整個程式碼如下:

#include <iostream>
using namespace std;

int main()
{
    int count = 0;//累加結果
    int add = 1;//單個值,一開始加的是1

    while(add <= 100)//大於100時就不迴圈了(等於100時還需迴圈)
    {
        count = count + add;//count加上add的值
        add = add + 1;//add每次迴圈加1
    }

    cout << "1加到100的值為:" << count;

    //此處暫停一下程式
    cin >> add;
    return 0;
}

5.問題拓展

很容易發現,如果要算1加到200,只需要將while迴圈判斷的條件改一下。如果我們需要同時輸出1加到100,和1加到200,難道需要複製整個程式碼然後再修改某一處嗎?我的經驗就是重複的程式碼越少越好,所以我們將問題抽象成1加到N的值是多少。抽象問題後,就可以寫成一個函式,來反覆執行通用的功能,只是引數條件變化了。和主函式一樣,定義一個普通的函式,取名為CalcCount:

//定義了一個函式,名字為CalcCount,返回值為int,引數為累加的上限
int CalcCount(int v_max)
{
    //TODO(TODO意為尚未完成的程式碼)
    return TODO;
}

接下來實現函式的運算過程,從主函式剪下過來,簡單修改一下(注意註釋也要更新!):

//定義了一個函式,名字為CalcCount,返回值為int,引數為累加的上限
int CalcCount(int v_max)
{
    int count = 0;//累加結果
    int add = 1;//單個值,一開始加的是1

    while(add <= v_max)//大於v_max時就不迴圈了(等於v_max時還需迴圈)
    {
        count = count + add;//count加上add的值
        add = add + 1;//add每次迴圈加1
    }

    return count;
}

在主函式,就使用CalcCount函式即可,只負責輸出顯示結果:

#include <iostream>
using namespace std;

//定義了一個函式,名字為CalcCount,返回值為int,引數為累加的上限
int CalcCount(int v_max)
{
	int count = 0;//累加結果
	int add = 1;//單個值,一開始加的是1

	while (add <= v_max)//大於v_max時就不迴圈了(等於v_max時還需迴圈)
	{
		count = count + add;//count加上add的值
		add = add + 1;//add每次迴圈加1
	}

	return count;
}

int main()
{
	//這裡直接將對應的值傳入CalcCount函式,返回計算後的值再顯示即可
	cout << "1加到100的值為:" << CalcCount(100) << endl;//再輸出一個endl用於換行
	cout << "1加到200的值為:" << CalcCount(200) << endl;
	cout << "1加到300的值為:" << CalcCount(300) << endl;
	cout << "1加到400的值為:" << CalcCount(400) << endl;
	cout << "1加到500的值為:" << CalcCount(500) << endl;

	//此處暫停一下程式
	int x;
	cin >> x;
	return 0;
}

執行程式,結果如下:

不過為了彰顯計算機擅於重複操作的說法,可以再寫一個迴圈語句,迴圈的輸出:

int main()
{
	int v_max = 1;
	while (true)
	{
		cout << "1加到" << v_max << "的值為:" << CalcCount(v_max) << endl;
		v_max = v_max + 1;
	}

	//此處暫停一下程式
	int x;
	cin >> x;
	return 0;
}

當v_max比較大的時候,輸出的結果也會更大。當輸出值超過int型別可以表示的範圍時,就會出現負數,至於為何是負數,以後再解釋。不過在很多遊戲裡應該見過不少數字過大變為負數的情況了。

6.演算法改進

很多人一說到演算法,就會覺得多麼高大上。的確也很高大上,高大的是研究演算法的人,新演算法的計算過程完成相同的事情,但計算所執行的步驟更加簡潔。如果使用上面的累加辦法,累加到N則需要進行N次加法,當N很大時,運算次數就特別多了。如果使用等差數列求和公式,那麼就只需要幾次計算了,公式如下:

S_{n}=na_{1}+\frac{n(n-1)}{2}d

由於首項為1,公差為1,則具體公式為:

S_{n}=n+\frac{n(n-1)}{2}=\frac{n^2+n}{2}

簡單代入100或200驗證得出結果一致,所以再編寫一個新演算法的函式:

//採用等差數列公式的計算方法
int CalcCount2(int v_max)
{
	return (v_max * v_max + v_max) / 2;
}

接著在主函式略微修改一下,同時輸出兩個函式的值,執行之後可以發現兩者輸出的值是一樣的:

	int v_max = 1;
	while (true)
	{
		cout << "1加到" << v_max << "的值為:" << CalcCount(v_max) << ", " << CalcCount2(v_max) << endl;
		v_max = v_max + 1;
	}

7.寫法簡化

上面為了方便理解沒有寫出最簡的寫法,這裡說明一下。

a = a + b的含義是計算a加上b的值後再賦值給a,比如一開始a為10,b為20,那麼執行之後a的值為30,b的值不變。a = a + b的寫法可以簡寫為a += b,如下:

a = a + b;//和下面一樣的功能
a += b;//簡寫

當b為正負1的時候,則有更簡化的寫法:

//自加1,三種寫法一樣
a = a + 1;
++a;//一般優先使用++a
a++;

//自減1,不過自減1一般用得較少
a = a - 1;
--a;//同樣一般優先使用--a,
a--;

8.判斷大小

在本例中還用到了判斷變數大小的邏輯,判斷a與b的大小通過以下操作符,返回真或假。作為while迴圈的條件,返回真時,while迴圈才會繼續執行,否則跳出迴圈,執行while後面外部的語句。這裡列出判斷大小的操作符,它和函式有點像,返回的是一個bool(布林)型別的值,它代表邏輯的真或假,也就是true或false,它可以作為while的條件判斷。

a < ba小於b時,返回真
a > ba大於b時,返回真
a <= ba小於或等於b時,返回真
a >= ba大於或等於b時,返回真
a == ba等於b時,返回真
a != ba不等於b時,返回真

結語

本章通過一個簡單的數學問題,示範了一些最基本的C++程式碼。同時還介紹了迴圈結構、斷點、函式的用法示例。在這個完整示例程式碼上你可以按自己的想法進行修改,從而深入理解本章的內容。下面為新手考慮,附上完整的程式碼:

#include <iostream>
using namespace std;

//定義了一個函式,名字為CalcCount,返回值為int,引數為累加的上限
int CalcCount(int v_max)
{
	int count = 0;//累加結果
	int add = 1;//單個值,一開始加的是1

	while (add <= v_max)//大於v_max時就不迴圈了(等於v_max時還需迴圈)
	{
		count += add;//count加上add的值
		++add;//add每次迴圈加1
	}

	return count;
}

//採用等差數列公式的計算方法
int CalcCount2(int v_max)
{
	return (v_max * v_max + v_max) / 2;
}

int main()
{
	int v_max = 1;
	while (true)
	{
		cout << "1加到" << v_max << "的值為:" << CalcCount(v_max) << ", " << CalcCount2(v_max) << endl;
		v_max = v_max + 1;
	}

	//此處暫停一下程式
	int x;
	cin >> x;
	return 0;
}