# 2024q1 Homework6 (assessment) contributed by <`Willsonbo`> ## M06: integration(二) ### 大數法則與資訊熵 1. **Shannon Entropy**: Shannon Entropy **H(S)** 用來量化一組資料的平均資訊量。它描述了資料中內在的不確定性或隨機性。公式為: $$ H(S)=−∑ i ​ P(s i ​ )logP(s i ​ ) $$ 其中 $P(s_i)$ 是字元 $s_i$ 出現的概率。 2. **大數法則**: 大數法則指出,當重複多次實驗時,結果的平均值會趨近於期望值。在資訊理論中,這表示當處理大量資料時,實際出現的概率分佈會趨近於理論分佈 。 ### 資料壓縮中的應用 **高概率集合**: 當我們尋找壓縮後錯誤概率小於 $\epsilon$ 的字串集合時,我們需要找到那些高概率出現的字串。這些字串被稱為$\epsilon$-高概率集合。 **壓縮比例**: 根據 Shannon 的理論,這樣的字串集合的總位元數約為 $2^n \cdot H(S)$。其中,$n$ 是原始字串的位元數。這表示如果原始字串長度為 $n$,則可以按照 Entropy $H(S)$ 的壓縮比例進行壓縮。壓縮比例為 $H(S)$,意味著壓縮後的位元數將大約是原始位元數的 $H(S)$ 倍。 ### 總結 - **高概率集合**:識別那些總出現概率高的字串集合,使壓縮後的錯誤概率小於 $\epsilon$。 - **壓縮結果**:總位元數為 $2^n \cdot H(S)$,壓縮比例為 $H(S)$,即資料越隨機(熵值越高),壓縮後所需位元數越多;資料越有規律(熵值越低),壓縮效果越好。 這意味著資料壓縮的效果取決於資料的熵值,熵值越高,壓縮率越低,反之亦然 。 假設我們有一個長度為 1000 位元的字串,經過分析得出其 Shannon Entropy 為 0.5。根據壓縮理論,我們可以預期將此字串壓縮到約 500 位元(即 1000 位元 * 0.5)。這樣,資料壓縮後的錯誤概率小於$\epsilon$,而壓縮效率達到最佳 。 當資料中每個隨機變數的機率與平均值差異越大,代表資料符合特定規律,資料的熵越小,我們可以用較少的位元表現這些資料,並用這些規律壓縮資料。 Fibonacci LFSR的實作是利用一個移位寄存器和異或門(XOR gates)來產生一個長度為 \(2^n - 1\) 的最大長度序列。以下是Fibonacci LFSR的實作說明: 1. **移位寄存器:** - 移位寄存器是一串可以存儲和移動位元的記憶體元件。在Fibonacci LFSR中,每一個位元在時鐘信號的驅動下會向右移動一位。 2. **抽頭回授:** - 在Fibonacci結構中,特定位置的位元會通過異或門反饋到移位寄存器的輸入端。這些特定位置稱為抽頭(tap)。例如,如果我們使用多項式 $x^5 + x^3 + 1$,則代表在第5位和第3位設置抽頭。 3. **XOR運算:** - 每次移位操作前,抽頭位的位元會進行異或運算,結果作為新的位元輸入到移位寄存器的最高位(左端)。 4. **具體實作:** - 設定初始值:將寄存器初始化為一個非零值。 - 每次時鐘脈衝: - 進行異或運算計算新的位元。 - 將移位寄存器右移一位。 - 將新位元輸入到最高位。 以下是一個簡單的C語言實作範例: ```c #include <stdint.h> void fibonacci_lfsr(uint64_t *reg) { uint64_t taps = ((*reg >> 5) ^ (*reg >> 3) ^ (*reg >> 2) ^ (*reg >> 0)) & 1; *reg = (*reg >> 1) | (taps << 63); } ``` 在這個範例中,我們使用了抽頭位5, 3, 2, 和0。每次調用函數時,寄存器會右移一位並將計算得到的新位元填入最高位。 :::danger 注意用語! 避免直接填入 ChatGPT 的內容。 ::: ```c static u_char __init get_hw_addr(struct net_device *dev, u_char * eeprom_image, char chipType) { int i, j, k; u_short chksum; u_char crc, lfsr, sd, status = 0; u_long iobase = dev->base_addr; u16 tmp; // 如果芯片類型是 LeMAC2 if (chipType == LeMAC2) { // 初始化CRC值為0x6a,並遍歷以太網地址長度(ETH_ALEN,一般為6) for (crc = 0x6a, j = 0; j < ETH_ALEN; j++) { // 從 EEPROM 中讀取硬件地址的一個字節,並存儲在設備的 dev_addr 中 sd = dev->dev_addr[j] = eeprom_image[EEPROM_PADDR0 + j]; // 將這個字節寫入網絡卡的參數寄存器 outb(dev->dev_addr[j], EWRK3_PAR0 + j); // 更新 CRC 值,對該字節的每一位進行計算 for (k = 0; k < 8; k++, sd >>= 1) { // 計算LFSR(線性反饋移位寄存器)值 lfsr = ((((crc & 0x02) >> 1) ^ (crc & 0x01)) ^ (sd & 0x01)) << 7; // 更新 CRC crc = (crc >> 1) + lfsr; } } // 如果計算出的 CRC 與 EEPROM 中存儲的不一致,設置狀態為 -1 表示錯誤 if (crc != eeprom_image[EEPROM_PA_CRC]) status = -1; } else { // 初始化 i 和 k for (i = 0, k = 0; i < ETH_ALEN;) { // k 左移一位 k <<= 1; // 如果 k 大於 0xffff,減去 0xffff if (k > 0xffff) k -= 0xffff; // 從 APROM 讀取一個字節並加到 k k += (u_char) (tmp = inb(EWRK3_APROM)); // 將讀取到的字節存儲到設備的 dev_addr 中 dev->dev_addr[i] = (u_char) tmp; // 將這個字節寫入網絡卡的參數寄存器 outb(dev->dev_addr[i], EWRK3_PAR0 + i); i++; // 從 APROM 再讀取一個字節,並將它的高8位加到 k k += (u_short) ((tmp = inb(EWRK3_APROM)) << 8); // 將讀取到的字節存儲到設備的 dev_addr 中 dev->dev_addr[i] = (u_char) tmp; // 將這個字節寫入網絡卡的參數寄存器 outb(dev->dev_addr[i], EWRK3_PAR0 + i); i++; // 如果 k 大於 0xffff,減去 0xffff if (k > 0xffff) k -= 0xffff; } // 如果 k 等於 0xffff,將 k 設為 0 if (k == 0xffff) k = 0; // 從 APROM 讀取兩個字節組成校驗和 chksum = inb(EWRK3_APROM); chksum |= (inb(EWRK3_APROM) << 8); // 如果計算出的 k 與校驗和不匹配,設置狀態為 -1 表示錯誤 if (k != chksum) status = -1; } // 返回狀態 return status; } ```