# Lec1. 期中考準備 [TOC] <br> ## 學校老師給的提示整理 ### Bit、Byte * 1 byte = 8 bit![image.png](https://hackmd.io/_uploads/SkBJnyrQ6.png) * [Bit補充](https://web.ntnu.edu.tw/~algo/Bit.html) <br> * 資料型態與使用多少bit ![image.png](https://hackmd.io/_uploads/BJ1tskS76.png) <br> ### 資料型態最大最小值與精準度 <br> * [各種整數最大最小值](https://cplusplus.com/reference/climits/) * 精準度(precision):實數最大值和實數精準度 * [資料型態、運算子與表示式](https://www.csie.ntu.edu.tw/~d00922011/ics/253/Lecture2-Type.pdf),P11頁 * [使用浮點數的觀念](http://blog.dcview.com/article.php?a=VmgBZFE5AzI%3D) * [浮點數精準度解說](https://cg2010studio.com/2012/03/30/cc-%E6%B5%AE%E9%BB%9E%E6%95%B8%E7%B2%BE%E6%BA%96%E5%BA%A6-floating-point-precision/) * [header cfloat (float.h)](https://cplusplus.com/reference/cfloat/) <br> * [overflow (溢位) and underflow (虧失)](https://www.educative.io/answers/what-are-overflow-and-underflow) <br> * recision (精確度) and accuracy (準確度) in floating-point calculations * [Microsoft](https://learn.microsoft.com/en-us/office/troubleshoot/access/floating-calculations-info) * [functions](https://www.tutorialspoint.com/precision-of-floating-point-numbers-in-cplusplus-floor-ceil-trunc-round-and-setprecision) <br> > 圖片來源:[Samsung](https://semiconductor.samsung.com/us/support/tools-resources/dictionary/bits-and-bytes-units-of-data/)、老師e3 <br> ### Inline與Macro :::spoiler Inline function (內嵌函數) vs. Macro fuction (巨集函數) * 都是拿空間換時間 * [內嵌函數](https://dotblogs.com.tw/v6610688/2013/11/27/introduction_inline_function) * [巨集函數](https://dotblogs.com.tw/Ace_Dream/2016/01/16/function_macro) ::: <br> ### util.c 中的函式 * 去除字串結尾的換行 ```cpp= void chop(char*p){ // remove trailing New Line if any if(p == 0 || *p==0) return; // 防呆一下 ! int len = strlen(p); // len 至少是 1 啦, WHY ? 因上面那句 if 擋掉空字串啦 if(p[len-1] == '\n') p[len-1] = 0; // Done } // chop( ``` <br> * 去除字串結尾換行,並把字串中的逗號換成空格 ```cpp= void chop2(char*p){ // 砍掉尾巴 new Line 並把裡面逗號換成空格 int len = strlen(p); char*pOLD=p; if(p[len-1] == '\n') p[len-1] = 0; // remove trailing '\n' if any while(*p) { // 把逗號都換成空格 //printf("%lld :: %c\n", p, *p); // Debug用, 偷看 p 指向何處 if(*p == ',') *p=' '; // 把 逗號 換成 blank ++p; // 別忘了前進一格 }// while( //printf("==%s==\n", pOLD); // Debug 用, 偷看看字串 p 目前變成怎樣 } // chop2( ``` <br> * 讀取long ```cpp= /// Usage: /// int many; long terms[88]; // 就不信你一次輸入 88 項 /// int many = readLongs(terms); // many 表示讀到幾項 int readLongs(long gg[ ]){ // 回傳讀到幾個 long 放入 gg[ ] char buf[99]; char * pEnd; // 參考 https://cplusplus.com/reference/cstdlib/strtol fgets(buf, sizeof buf, stdin); chop2(buf); //會把 trailing new Line 去掉, 且把逗號全換成空格 gg[0] = strtol(buf, &pEnd, 10); // 先抓一個 long if(buf == pEnd) return 0; // 表示strtol()沒看到任何有用數字資料 /// 新增! int i = 1; // 已經讀入一個到 gg[0] 所以接下來是要讀入到 gg[1] while(pEnd != 0 && *pEnd != 0){ // 注意就這樣寫 !! char * pOLD = pEnd; /// 新增!備份 pEnd 以便呼叫strtol()之後比對檢查 gg[i] = strtol(pEnd, &pEnd, 10); // 繼續抓 long 到沒有 data 為止 if(pOLD == pEnd) break; // 表示已沒數字; 這 gg[i] 獲得 0 但我們不要它 ! /// 新增! ++i; //準備抓下一個 gg[i] } // while( return i; // got total i items } // readLongs ``` <br> ### Lazy Evaluation * [Wiki](https://zh.wikipedia.org/zh-tw/%E6%83%B0%E6%80%A7%E6%B1%82%E5%80%BC) * [[C++] Lazy Evaluation for Function Argument](https://shininglionking.blogspot.com/2018/08/c-lazy-evaluation-for-function-argument.html) * [CSDN - C++程式設計:lazy evaluation](https://blog.csdn.net/zhizhengguan/article/details/113334970) <br> ### Call Stack Frame * [Wiki](https://en.wikipedia.org/wiki/Call_stack) * [影片](https://www.youtube.com/watch?v=Q2sFmqvpBe0) ```cpp= myfun(arg1, arg2, .. , argn); // will return from function to here int myfun( . . . ) { //Local var 1; // Local var 2; .. // Local var n // statements } // myfun /// Call Stack Frame ``` ![image.png](https://hackmd.io/_uploads/SJnkUlSQT.png) ![image.png](https://hackmd.io/_uploads/Hyg78grQa.png) <br> ### static local vs. auto vs. static global >變數的左邊如果補了 static 這前綴語, 會影響編譯器對變數的處理方式 ! auto Local 變數每次進入函數重新在堆疊區(Stack)生出, 離開函數時就把記憶體還掉; static local 變數會被偷移到函數外面, 生命祈與程式一樣,但進入函數才能使用, 離開函數暫時不能用。 Global 變數本來就是靜態(static)變數, 但加了 static 前綴語後意思是 static to this FILE, 就是說只在這檔案的函數可以使用。 典型 static global 變數最佳範例就是PRNG亂數產生器的 rand( ) 和 srand( ) 共用的 seed (種子)。 所以 rand( ) 和 srand( ) 一定要寫在同一個檔案。(C 語言程式庫的函數大多是一個函數一個檔案, WHY?) <br> ### function -- 函數 ? 函式 ? 副程式(subroutine)? 程序(Procedure)? * [參數傳遞](https://home.gamer.com.tw/artwork.php?sn=5007107) * 函數參數傳遞注意事項: (C 嚴格說就只有 整數和實數) > 比 int 短的整數先轉成 int 再傳過去(塞入堆疊參數區); > 比 double 短的實數(阿就 float)先轉成 double 再傳過去 ! * [enum](https://www.runoob.com/cprogramming/c-enum.html) <br> ### ctype.h ctype.h 裡面很多簡單好用函數 isdigit, isupper, islower, toupper, tolower, ... ►►Apple 公司的 isdigit.c, atol.c 和 strtol.c <br> --- <br> ## 筆試相關內容 ### #1. EUV與DUV 報紙報導說荷蘭聯合美國打壓中國, 說不只 EUV, 連 DUV 也不賣中共 >:::spoiler **(a) 啥是 EUV? 啥是 DUV ?** > 微影設備是利用光線的波長來加工精密尺寸的晶片,又稱蝕刻機、光刻機;波長不同效率差很大。最早是使用汞燈產生的紫外光源,再來是深紫外光源(Deep Ultraviolet;DUV),波長可從365奈米縮減到193奈米;最新技術的極紫外光源(Extreme Ultraviolet;EUV),更將波長縮減至13.5奈米。 > 目前以DUV設備應用最廣、需求也最大;僅台積電、三星等少數具7奈米及其以下製程能力業者,才會使用EUV。EUV相較於DUV能夠提供更高的解析度和製造更小尺寸的元件。 >::: >:::spoiler **(b) EUV 機器一台的重量大約多少 ?** >EUV機器通常非常龐大,一台的重量大約在數十噸到幾百噸不等。這些機器需要龐大的設備來製造極細微的晶片元件。新一代ASML High-NA EUV曝光機比前一代體積大30%左右,重量超過200公噸,至少需要三架波音747分批運送。 >::: >:::spoiler **(c\) 像 EUV、ROC、ECFA 等這種由一些英文字的字首組成的字叫做甚麼?寫出其中文和英文全稱。** >EUV、ROC、ECFA等這種由一些英文字的字首組成的字,通常稱為縮寫 (Acronym)。中文全稱為「縮寫詞」,而英文全稱為「Acronym」。這些縮寫詞的使用有助於簡化表達,特別在科技領域中常被使用,以便於描述複雜的概念或名詞。而EUV、ROC、ECFA的部分,則分別為極紫外光 (Extreme Ultraviolet)、台灣(Republic of China)、峽兩岸經濟合作架構協議(ross-Strait Economic Cooperation Framework Agreement)。 >::: <br> ### #2. ERP悖論 2022年諾貝爾物理獎頒發給三位證明 EPR悖論其實是 EPR佯繆 ! > :::spoiler **(a) 啥是EPR悖論? 簡單說明(包括 EPR 這字啥意思)** > EPR悖論是由愛因斯坦(Albert Einstein)、波多夫斯基(Boris Podolsky)和羅森(Nathan Rosen)提出的概念。EPR是這三位物理學家姓氏的首字母縮寫。 > 這個悖論關於量子力學中的「量子紋理性」(Quantum Entanglement),即兩個或更多個粒子之間的特殊相互關係。EPR悖論基於對於量子紋理性的理解,即如果兩個粒子在某個時刻曾相互作用,之後分開並移動到非常遠的地方,對其中一個粒子的測量結果將立即影響另一個粒子的狀態,即使這兩個粒子之間的通信速度超過了光速。這引發了愛因斯坦對於量子力學的一些基本原理和量子紋理性的本質的質疑,並提出了這個被稱為EPR悖論的問題。 > ::: > :::spoiler **(b) 為何有些報導說是該三位物理學家證明了貝爾不等式在量子力學不成立?貝爾不等式和EPR悖論啥關係?** > EPR悖論和貝爾不等式關係密切。在1964年,約翰·貝爾(John Bell)提出了貝爾不等式,試圖檢驗量子力學是否可以符合我們所謂的局部實在論(Local Realism)。貝爾不等式主要是為了評估在經典物理學框架下,是否可以解釋量子紋理性所產生的結果。 > 當科學家應用貝爾不等式來測試EPR紋理性時,他們發現量子力學的預測結果與貝爾不等式所預測的經典物理結果不同。這意味著量子力學的解釋不符合傳統的局部實在論。這種不一致性對於認識量子力學和我們對物理世界的理解有深遠的影響。 > ::: > :::spoiler **(c\) 這個物理學獎和電腦有啥關係 ?** > 物理學獎與電腦有許多關聯,特別是在計算機科學和量子計算方面。例如,諾貝爾物理學獎經常頒發給在物理學領域做出重大貢獻的科學家,這些貢獻有時也直接或間接地影響了計算機科學領域。 > 特別是近年來,量子計算在計算機科學中扮演了重要的角色。這領域的發展可能會改變我們對計算和資訊處理的認識,並且有可能帶來革命性的變化。獲得物理學獎的研究成果和對量子力學的深入理解,為量子計算的發展提供了重要基礎。量子計算可能會帶來革命性的技術和計算能力,有望影響到未來的計算機科學和相關領域。 > ::: <br> ### #3. HSM與RSA > ATM提款機內有電腦(大部分跑Windows)與 HSM > :::spoiler **(a) 啥是 HSM, 英文全稱與中文名稱 ? 用途或目的是啥 ?** > HSM代表硬體安全模組(Hardware Security Module),中文名稱為硬體安全模塊。HSM是一種專用硬體裝置,旨在保護和管理加密密鑰、數位簽章以及其他敏感資訊。其主要目的是提供高度安全的密碼操作和存儲,通常被用於加密操作、密碼保護、金融交易等敏感資訊的存儲和管理,比如在銀行、金融機構或支付系統中用於保護金融交易資訊。 > ::: > :::spoiler **(b) 啥是 RSA 演算法 ? 與 HSM 啥關係 ?** > RSA演算法是一種非對稱式加密演算法,由Rivest、Shamir和Adleman三位數學家於1977年提出。RSA演算法使用了兩個密鑰:一個是公鑰(用於加密)、另一個是私鑰(用於解密)。RSA演算法基於大數質因數分解難題,能夠確保資料的機密性和完整性。HSM通常用於生成、存儲和保護RSA密鑰,因為RSA密鑰的保護是至關重要的,而HSM提供了一個安全的環境來執行這些關鍵操作。 > ::: > :::spoiler **(c\) 自然人憑證以及 https 和它有啥關係?** > 自然人憑證是用於在網際網路上進行安全身份驗證的數位證書,用來證明個人在線交易中的身份。HTTPS(超文本傳輸安全協定)則是一種通過SSL/TLS進行網頁傳輸的安全協定,能夠確保在互聯網上傳輸的資訊被加密,避免敏感資訊在傳輸過程中被竊取或竄改。自然人憑證通常用於HTTPS連接,確保使用者在網絡上的安全身份驗證,從而保護用戶在網路上的隱私和資訊安全。 HSM在這個過程中可能會被用來安全地存儲和管理這些憑證和相關密鑰,確保加密和解密操作的安全性。 > ::: <br> ### #4. 馮紐曼架構和馮紐曼瓶頸 > :::spoiler **簡單解釋馮紐曼架構(范紐曼架構) 和馮紐曼瓶頸, 並列出至少兩項被用來克服馮紐曼瓶頸的技術(也要簡單解釋)。** > 馮紐曼架構: > 馮紐曼架構是一種計算機架構設計,由約翰·馮紐曼(John von Neumann)提出。它是一種將程序指令和資料一起存儲在記憶體中的計算機結構。馮紐曼架構包括中央處理器(CPU)、記憶體、輸入和輸出設備,以及用來存儲程序指令和資料的記憶體。 > > 馮紐曼瓶頸: > 馮紐曼瓶頸是指在馮紐曼架構中,由於各組件的運作速度不一致或其他限制導致系統整體效能受到限制的情況。這可能是計算資源、記憶體速度、I/O速度或其他系統元件的不平衡,導致某個元件的速度限制了整個系統的效能。 > > 克服馮紐曼瓶頸的技術: > > 並行處理(Parallel Processing):透過將多個處理器或核心同時應用於執行任務,提高整體系統的運算速度。這樣可以分散計算負荷,提高系統效能。 > 快取記憶體(Cache Memory):使用高速快取記憶體來暫存CPU常用的指令和資料,以減少對主記憶體的存取需求,從而提高系統執行效率。 > ::: <br> ### #5. C 語言中的條件式表示 烏克蘭決定如果(年齡 >= 18 而且 身高 >=158 而且 體重 >=49) 抓去當兵 請用 C 語言以下兩種語法各寫一條件式表示之: (印出"抓去當兵" 或 印出"這個不抓") > :::spoiler **(a)compound conditional 複合條件式** > ```c= > // (a) Compound Conditional 複合條件式 > > if (age >= 18 && height >= 158 && weight >= 49) { > printf("抓去當兵\n"); > } else { > printf("這個不抓\n"); > } > > ``` > ::: > :::spoiler **(b)nested conditional 巢狀條件式** > ```c= > // (b) Nested Conditional 巢狀條件式 > > if (age >= 18) { > if (height >= 158) { > if (weight >= 49) { > printf("抓去當兵\n"); > } else { > printf("這個不抓\n"); > } > } else { > printf("這個不抓\n"); > } > } else { > printf("這個不抓\n"); > } > > ``` > ::: > <br> ### #6. 暫存器NZVC或NZOC CPU 內通常有數個甚至十幾個暫存器(Register),一定會有一個用來指向下一個要執行的指令的 Program Counter(簡稱PC), 還有專門做運算的例如 A 暫存器(A 是 Accumulator的首字母),也有的作用是幫忙存取 array 陣列某元素的索引(index)暫存器,另外通常會有一個每個 bit 有不同意義的暫存器,其中會有四個很重要的 bit 通常稱為 NZVC 或 NZOC,可以 Google NZVC bit 找幾篇看看。簡單解釋這些NZVC或NZOC的 bit 和 C 語言程式中哪些敘述有關? > :::spoiler **NZVC或NZOC** > NZVC 或 NZOC 通常代表四個旗標位(Flag Bits)的縮寫。這些旗標位用於表示 CPU 運算後的結果狀態,每個 bit 代表不同的狀態: > > N (Negative) bit:當運算結果為負時,N bit 被設置為1。 > Z (Zero) bit:當運算結果為零時,Z bit 被設置為1。 > V (Overflow) bit:在有符號數字的運算中,當運算結果溢出時,V bit 被設置為1。 > C (Carry) bit:在無符號數字的運算中,當運算結果產生進位時,C bit 被設置為1。 > 在 C 語言中,這些旗標位通常與位操作和控制流程語句相關。例如: > > 位操作:可用位運算符號(&、|、^、~)來檢查或設置這些旗標位的值,如 if (NZVC & 0x8) 來檢查 Overflow(V)位是否為1。 > 控制流程語句:根據這些旗標位的狀態,可以使用條件語句(如 if、else if)來執行相應的程式碼段。例如,if (NZVC & 0x2) 來檢查 Zero(Z)位是否為1,然後根據這個條件執行相應的程式碼。 > 這些旗標位在程式執行時提供了對運算結果狀態的反饋,可以根據這些狀態控制程式的流程和行為。 > ::: <br> ### #7. 改錯 - 指標 以下這程式執行就會當掉, 解釋為甚麼? ```c= #include <stdio.h> int* ggyy = 0; int main( ) { printf("Test pointer and *pointer\n"); fflush(stdout); *ggyy = 3388; printf("Still Alive?\n"); return 0; // 表示正常結束 } // main( ``` > :::spoiler **空指標導致在賦值時的無效記憶體位置** > 這段程式在執行時會導致程式崩潰(crash)或產生未定義行為(undefined behavior)。問題在於指標 ggyy 指向了空指標(null pointer)。 > > 在程式中,int* ggyy = 0; 將指標 ggyy 設置為空指標(null pointer),這意味著它不指向任何有效的記憶體位置。 > > 然後,程式嘗試將值 3388 賦給 ggyy,也就是嘗試將 3388 存入空指標所指向的記憶體位置。由於空指標並不指向有效的記憶體位址,這將導致未定義行為,通常導致程式當掉或崩潰。 > > 當程式嘗試對空指標解除引用時,系統會試圖存取一個未知的記憶體位置,這可能導致系統拋出異常或程式崩潰。 > > 要避免這種情況,應確保在對指標進行解除引用(dereferencing)之前,指標應該指向一個有效的記憶體位址。* > ::: <br> ### #8. 關於參數和Local變數在記憶體的安排 假設主程式中呼叫 myfun(arg1, arg2, arg3); 然後 myfun( ) 函數內依序有三個變數 v01, v02, 和 v03; 畫一張簡單圖展示並簡單說明 arg1, arg2, arg3, v01, v02, v03 和 return address 在記憶體內的狀況。 > :::spoiler **圖** > ```sql > | Higher memory addresses | > |------------------------------------| > | v03 (Local variable) | > | v02 (Local variable) | > | v01 (Local variable) | > | Return address | > | arg3 (Parameter) | > | arg2 (Parameter) | > | arg1 (Parameter) | > |------------------------------------| > | Lower memory addresses | > > ``` > ::: > :::spoiler **說明** > 參數 (arg1, arg2, arg3):這些是由主程式傳遞給 myfun 函數的參數,儲存在一個被稱為「堆棧(stack)」的記憶體區域中。 它們按照呼叫的順序被壓入堆疊中,位於較低的記憶體地址。 > > 局部變數 (v01, v02, v03):這些是 myfun 函數內的局部變數,也儲存在堆疊中。 它們會在函數內部執行時被創建,也按照宣告的順序在堆疊中分配空間。 通常隨著函數的執行而動態分配和釋放記憶體。 > > Return address:當函數完成後,系統需要知道返回主程序的位置,因此在堆疊中存放了返回地址。 當函數執行完畢後,程式會跳回此位址,繼續主程式的執行。 > > 在堆疊中,參數和局部變數的分配是按照一種「後進先出」的方式運作的,即最後進入堆疊的資料最先被取出,這也符合函數的呼叫和返回流程。 > ::: <br> ### #9. 關於 C 的均一分佈的亂數 rand( ) 程式庫函數 > :::spoiler **(a) 簡單解釋為何說 rand( ) 是 PRNG ?** > rand() 是 PRNG 的意思是偽隨機數產生器(Pseudo-Random Number Generator)。 它是一個按照特定演算法產生看似隨機但實際上是根據初始種子值計算出來的序列。 這種產生的數列在每次程式啟動時以相同的種子值開始,因此不是真正的隨機數產生器,而是根據某個演算法產生的偽隨機數序列。 > ::: > :::spoiler **(b)寫一句運算式 int ans = ... ; 可讓 ans 得到 [60, 100] 的整數 (就是60到100,包括60也包括100)** > ```cpp= > int ans = rand() % 41 + 60; > ``` > 這樣的表達式將取得一個範圍在 0 到 40 的隨機整數,然後將其加上 60,這樣就會得到 60 到 100 之間的整數。 > ::: > :::spoiler **(c\)寫一句運算式 double x = ...; 可讓 x 得到 [0, 1) 的實數 (就是包括0, 但不包括 1.0)。** > > ```c= > double x = (double)rand() / (RAND_MAX + 1.0); > ``` > 這個表達式將 rand() 返回的隨機數除以 RAND_MAX(RAND_MAX 是 rand() 函數返回的最大值)得到一個 [0, 1) 之間的浮點數。 > > ::: <br> ### #10. 基礎電腦概念(以下abcd任選三個作答) > :::spoiler **(a) 簡單說一下 ABC 和 ENIAC 的恩怨情仇, 不可以超過250字。** > ABC (Atanasoff-Berry Computer) 是由Atanasoff和Berry在1942年設計的電腦,ENIAC (Electronic Numerical Integrator and Computer) 則是在1946年由Eckert和Mauchly開發。ENIAC後來被視為世界上第一部電子數值積分電腦,而Atanasoff也提起法律訴訟,聲稱ENIAC的開發侵犯了他們的專利。這場爭端影響了電腦發展歷史。 > ::: > :::spoiler **(b) 簡單比較 DRAM 和 SRAM, 包括它們的原理和主要特性。** > DRAM (Dynamic Random Access Memory) 是一種動態隨機存取記憶體,存儲資料需要定期刷新以保持資料。SRAM (Static Random Access Memory) 是一種靜態隨機存取記憶體,不需要定期刷新。DRAM存取速度較慢,但密度高,成本低;SRAM存取速度快,但成本高且密度較低。 > ::: > :::spoiler **(c\) 每次存取記憶體大約多久? 每次存取磁碟大約多久? (大約即可)** > 存取記憶體約為數納秒(ns),而存取磁碟則在數毫秒(ms)級別。 > 記憶體存取時間 10ns (nano second), 硬碟存取速度 100MB/sec。 > ::: > :::spoiler **(d) "不可數"和"不可量"和"不可說"以及"不可說不可說"哪個比較大?** > "不可說不可說"比較大。 > ::: <br> ### #11. 基礎電腦概念 > :::spoiler **(a) 啥是 Program counter? Instruction pointer? Instruction Register?** > Program counter: 存儲下一條要執行指令的記憶體地址。 > Instruction pointer: 通常是 CPU 中的寄存器,用來存儲目前執行指令的記憶體地址。 > Instruction Register: 存儲正在執行的指令。 > ::: > :::spoiler **(b) 簡單解釋 Fetch-Decode-Execute cycle** > Fetch-Decode-Execute cycle 是指 CPU 執行指令的基本過程:從記憶體中取出指令(Fetch)、對指令進行解碼(Decode),並執行(Execute)該指令。 > ::: > :::spoiler **(c\) 簡單比較 program 和 process (不可以超過66字)** > Program:指的是靜態的程式碼或指令集,通常存儲於儲存媒體中,如硬碟或記憶體。 > Process:是在執行中的程式,包括正在運行的程式碼、資源使用情況等。 > ::: <br> ### #12. sizeof 和 strlen 假設程式寫了類似如下: ```cpp= int idTBL[ ]={ 10, 11, 12, 999, }; ``` > :::spoiler **(a) 簡單舉例說明 sizeof 和 strlen 的差別。** > sizeof 是一個運算符,用於計算數據類型或變量的字節大小,而 strlen 是一個函數,用於計算字串的長度。 > ::: > :::spoiler **(b) 請簡單解說 sizeof(idTBL)/sizeof(int) 這答案是啥以及可做啥用?** > 這段程式用於計算 idTBL 整數陣列的元素數量。除以 sizeof(int) 是因為 sizeof(idTBL) 返回的是整個陣列的字節大小,除以每個元素的字節大小能計算出陣列的元素數量。 > ::: <br> ### #13. 簡單解釋啥是 Overflow ? 並寫一小段簡單 C 程式, 用 加法 和 for Loop 和 printf( )印出 short int 整數,在 Overflow 前後各約三個或四個數值,程式一小段即可, 不必寫完整程式, 但要說明會印出啥。 > :::spoiler **簡單解釋** > Overflow 是指當數值超過其資料類型所能容納的範圍時發生的情況。在進行數值運算(例如加法或乘法)時,如果結果超過了該資料類型所能表示的最大值,便會導致 Overflow。在大多數程式語言中,當數值超出資料類型的範圍時,會發生溢位,導致數值從該類型的最大值“溢出”到最小值,或者循環回其他範圍。 > ::: > :::spoiler **程式** > 從SHRT_MAX(short int 的最大值)-3 開始,進行加法運算。在前四次加法運算後,數值會持續增加,但在 short int 的範圍內,直到達到最大值為止。繼續加法運算將導致溢位,數值會循環回到最小值,然後持續增加直到下一次溢位。這個循環的過程反映了Overflow的情況。 > ```c= > #include <stdio.h> > #include <limits.h> > > int main() { > short int num = SHRT_MAX - 3; // short int - 3 > printf("Before Overflow:\n"); > for (int i = 0; i < 4; i++) { > printf("%d\n", num); > num = num + 1; // 進行加法運算,導致溢位 > } > printf("After Overflow:\n"); > for (int i = 0; i < 4; i++) { > printf("%d\n", num); > num = num + 1; // 持續加法運算,數值已經溢位,結果無法被正確表示 > } > return 0; > } > ``` > 印出: > ``` > Before Overflow: > 32764 > 32765 > 32766 > 32767 > After Overflow: > -32768 > -32767 > -32766 > -32765 > ``` > ::: <br> ### #14. 簡單解釋啥是 Underflow ? 並寫一小段簡單 C 程式, 用乘法和 for Loop 和 printf( )印出 double 值 (或者 float 值也可) 在 Underflow 前後各約三個或四個數值,不必完整程式,但要說明會印出啥(大概即可)。 > :::spoiler **說明** > Underflow指的是數值太接近浮點數表示的最小值,導致失真或精度損失。在浮點數表示中,當一個數值太小,接近或低於所能表示的最小非零值時,將發生Underflow。這可能導致精度損失或結果變成零。 > ::: > :::spoiler **程式** > ```c= > #include <stdio.h> > #include <float.h> > #include <math.h> > > int main() { > float num = FLT_MIN*8; // 最小非零的float值*8 > printf("Before Underflow:\n"); > for (int i = 0; i < 4; i++) { > printf("%1.38f\n", num);//印出38位小數 > //-37 or smaller: Minimum negative integer value for the exponent of a base-10 expression that would generate a normalized floating-point number. > num = num / 2; // 進行除法運算,逼近浮點數的最小非零值 > } > printf("After Underflow:\n"); > for (int i = 0; i < 4; i++) { > printf("%1.38f\n", num); > num = num / 2; // 持續除法運算,結果會變得非常接近零 > } > return 0; > } > ``` > 印出: > ``` > Before Underflow: > 0.0000000000000000000000000000000000001 > 0.0000000000000000000000000000000000000 > 0.0000000000000000000000000000000000000 > 0.0000000000000000000000000000000000000 > After Underflow: > 0.00000000000000000000000000000000000001 > 0.00000000000000000000000000000000000000 > 0.00000000000000000000000000000000000000 > 0.00000000000000000000000000000000000000 > ``` > :::