高中數學拓展/數學程式設計
在我們開始之前
- 本章不會嘗試嚴格地教你如何程式設計。因此,強烈建議您具備 C 語言的基本工作知識。建議您在學習本章內容之前儘可能多地瞭解 C 語言。
- 如果您不熟悉程式設計或 C 語言,請閱讀 About.com 上的 "C 語言教程" 的前 7 課。
隨著您獲得程式設計經驗,您會更欣賞更具體的解釋,例如 C 語言華夏公益教科書。
程式設計簡介
程式設計有很多用途。程式設計和計算機科學在人工智慧和統計學等領域非常重要。程式設計允許您靈活地使用計算機,並非常快地處理資料。
編寫程式時,程式被寫入人類可以理解的文字形式。但是,計算機不直接理解人類寫的程式。它需要被轉換成計算機可以理解的方式。
例如,計算機就像一個閱讀和說德語的人。你用英語寫和說。您寫給計算機的信件需要被翻譯,以便計算機能理解。負責這項工作的程式被稱為編譯器。
你需要編譯你的類似英語的指令,以便計算機能理解。一旦程式被編譯,它就很難“反編譯”,或者將其轉換回英語。程式設計師編寫程式(用我們的比喻,用英語),稱為原始碼,它是程式的人類可讀定義,然後編譯器將其翻譯成“機器程式碼”。我們建議使用廣泛可用的 gcc 編譯器。
當我們在這裡研究數學程式設計時,我們將看看如何編寫程式來解決一些困難的數學問題,這些問題通常需要花費我們很多時間才能解決。例如,如果我們要找到多項式x5+x+1 的根的近似值 - 這對人類來說非常難。但計算機可以輕鬆解決這個問題 - 如何?
程式語言基礎
在本章中,我們將使用 C 語言,請透過閱讀 About.com 上的 "C 語言教程" 的前 7 課來了解 C 的基礎知識。
C語言示例程式
資料型別
大小限制:標頭檔案 limits.h 和 float.h
計算機是基於布林邏輯的機器。這意味著計算機基於某種區分狀態為真或假,或設定和未設定的方法。抽象地說,我們認為計算機使用 1 代表真或設定,使用 0 代表假或未設定。我們將這些 1 和 0 稱為位。在計算機中,我們不將資訊作為位來跟蹤。相反,計算機中的資訊儲存在稱為位元組的可定址塊中。位元組是計算機中可以訪問的最小記憶體片段,它不是位。當我們在 C 程式中宣告一個 [標量] 變數時,該記憶體具有一個地址和一個長度。地址表示記憶體從哪裡開始,長度表示表示變數使用多少個位元組。
包含檔案 <limits.h> 用於定義可定址整數型別的尺寸,包含檔案 <float.h> 用於定義可定址浮點型別的尺寸。這些檔案中的值依賴於編譯器和計算機。這意味著如果您更改編譯器或在不同型別的計算機上編譯程式,它可能會以不同的方式執行。
以下是在這兩個檔案中定義的一些值
練習
用整數程式設計
離散程式設計處理整數以及如何在計算機中操作它們。
整數運算
理解整數除法
在 C 中,命令
- int number;
- number = 3 / 2;
將在計算機記憶體中預留一些空間,我們可以透過變數名稱number來引用該空間。 在計算機看來,number是一個整數,僅此而已。 之後
- number = 3 / 2;
numbers 等於 1,而不是 1.5,這是因為當/應用於兩個整數時,只會給出結果的整數部分。 例如在 C 中
- 5 / 2 等於 2
- 353 / 3 等於 117
- -5 / 2 等於 -2
- 353 / -3 等於 -117
- -5 / - 2 等於 2
如果您正在測試的數字介於 1 和 -1 之間 - 例如 2 / 5 或 -2 / 5,則結果未定義,儘管大多數編譯器返回 0。
模運算子, %,返回整數除法產生的餘數。 例如在 C 中
- 5 % 2 等於 2
- 353 % 3 等於 2
- -5 % 2 等於 -2
- 353 % - 3 等於 2
- -5 % -2 等於 -1
結果的符號與您預期的被除數的符號相同。 對於介於 1 和 -1 之間的分數,結果與分子相同。
練習
練習 1
寫下您對探索除法和模運算的程式應該做什麼的想法。
- 需要進行哪些處理?
- 您有哪些型別的輸入?
- 您的輸出是什麼樣的?
以下示例將引導您完成此練習。
C 程式示例,用於練習 1
遞迴定義函式的建模
階乘函式 n! 遞迴定義為
- 0! = 1
- n! = n×(n-1)! if n ≥ 1
在 C 中,如果 fact(n) 是如上所述的函式,我們希望
- ; if
我們應該注意到所有遞迴定義的函式都有一個終止條件,在這種情況下,函式可以直接給出答案,例如 fact(0) = 1。
我們可以使用以下程式碼輕鬆地對階乘函式進行建模,然後執行它
- int fact (int n)
- {
- if (n == 0)
- return 1;
- if (n >= 1)
- return n * fact(n - 1);
- if (n == 0)
- }
上面的 C 函式非常自然地對階乘函式進行了建模。 為了測試結果,我們可以編譯以下程式碼
- #include <stdio.h> /* 標準輸入輸出標頭檔案 */
- int fact (int n)
- {
- if (n == 0)
- return 1;
- if (n >= 1)
- return n * fact(n - 1);
- if (n == 0)
- }
- int main(void)
- {
- int n = 5;
- printf("%d", fact(n)); /* printf 在 stdio.h 中定義 */
- }
我們也可以對斐波那契數函式進行建模。 設 fib(n) 返回第 (n + 1) 個斐波那契數,以下內容應該清楚
- fib(0) 應該返回 1
- fib(1) 應該返回 1
- fib(n) 應該返回 fib(n - 1) + fib(n - 2); 對於 n ≥ 2
我們可以使用 C 對上述內容進行建模
- int fib (int n)
- {
- if (n == 0 || n == 1) /* 如果 n = 0 或如果 n = 1 */
- return 1;
- if (n >= 2)
- return fib(n - 1) + fib(n - 2);
- if (n == 0 || n == 1) /* 如果 n = 0 或如果 n = 1 */
- }
同樣,您將看到對遞迴函式進行建模並不難,因為它只涉及將數學翻譯成 C 程式碼。
對非遞迴函式進行建模
有一些函式只涉及整數,並且可以使用 C 中的函式很好地對它們進行建模。 階乘函式
- f(n) = n! = n(n - 1)(n - 2) ... 3×2×1
可以使用以下程式碼簡單地建模
int n = 10; //get factorial for 10
int f = 1; //start f at 1
while(n > 0) //keep looping if n bigger then 0
{
f = n * f; //f is now product of f and n
n = n - 1; //n is one less (repeat loop)
}
浮點程式設計
程式不僅可以使用整數值編寫,還可以使用各種形式的浮點值編寫。 您通常應該使用double關鍵字來定義浮點數; 這樣做的原因是,在許多情況下,用浮點算術編寫表示式的直觀方法是次優的。 浮點算術是非結合性的 - 在以 10 為基數的系統中,具有 2 位精度的系統具有 (1.0 + 0.02) + 0.04 = 1.0(向下舍入,因為 1.02 舍入為 1.0,然後 1.04 向下舍入為 1.0),但 1.0 + (0.02 + 0.04) = 1.0 + 0.06 = 1.1。 還存在一個float型別,它使用 4 個位元組而不是 8 個位元組,但除非您知道自己在做什麼,否則不應該使用它,因為只有 24 位精度,或者大約 9 個以 10 為基數的有效數字。
注意:如果您使用 2 個整數運算元,它仍然執行整數運算,因此它列印 1,而不是您預期的 1.5
- double number;
- number = 3/2;
- printf("%f\n",number);
定義浮點數然後計算 3/2 的示例
- double number = 3;
- number /= 2;
- printf("%f\n",number);
需要注意的是:浮點數不能完美地表示所有十進位制數。 顯然,由於變數佔用的記憶體是有限的,它不能表示無限數量,而只能表示它的近似值。 此外,某些數字無法在浮點中完美表示。 在這段程式碼中
- double number;
- number = 1/10;
number 的值不是 0.1,而是實際上是 0.10000000000000001。
這種限制的一個類比是 1/3 的值。 在十進位制系統中,此值不能用有限數量的 3 來精確表示,如 0.333... 由於 2 和 5 是 10(十進位制系統的基數)的唯一質因數,因此只有分母包含 2 和 5 的乘積的分數,例如 5/8 或 231/250 (但不是 1/3 或 5/14)可以透過十進位制數(分別是 0.625 和 0.924)精確表示。
計算機使用以 2 為基數的算術,因此只有分母包含 2 的乘積(2 的冪)的分數,例如 5/8 或 231/256 (但不是 231/250、1/3 或 1/10,如上所述)可以透過浮點數精確表示。
反饋
您怎麼看? 太容易還是太難? 資訊太多還是不夠? 我們怎樣才能改進? 請透過在討論標籤中發表評論來告知我們。 更好的是,自己編輯它並使其更好。