Java 入門指南 - 修正後的數學公式

程式中可能會發生的錯誤有三種,分別是語法錯誤 (syntax error) 、執行期間錯誤 (run-time error) 及語意錯誤 (sematic error)




編譯器 (compiler) 會直接幫我們挑出語法錯誤,例如打錯識別字 (identifier) 名稱或是漏打分號等等。執行期間錯誤的話, Java 另有例外處理 (exception handling) 的機制,讓我們可以處理開啟指定檔名,而檔案不存在的情況。三種錯誤中最麻煩的,就是語意錯誤了,因為有語意錯誤的程式,程式可以順利執行完畢,卻跑出錯誤的結果。


我們的 Encrypt 類別 (class) 目前正是碰到了發生語意錯誤的情況,這是說
y = a * x + b
m = y % n
r = m + diff


其中 a 與 b 若是 0 到 9 隨機整數,有些組合成立,可以得到正確結果,有些組合卻會得到錯誤的結果,這是為什麼呢?嗯,好麻煩唷!這樣就得討論好多數學,打斷我們發展程式的腳步,所以我們不打算仔細討論這背後的數學理論,我們繼續測試,直接來找出哪些組合會得到錯誤的結果吧!


要知道哪些組合可能會發生錯誤,我們就得知道 a 與 b 的值,這不難,印出來就看得到了
// 測試 Encrypt 的類別
public class EncryptDemo {
    public static void main(String[] args) {
        System.out.println();
        // 印 16 次表格,最後印出 (a, b) 的值
        for (int i = 0; i < 16; i++) {
            Encrypt t = new Encrypt();
            t.setArray();
            System.out.print(t.cArray);
            System.out.print(", ");
            System.out.print(t.a);
            System.out.print(", ");
            System.out.print(t.b);
            System.out.print("\n");
        }
        System.out.println();
    }
}

/* 《程式語言教學誌》的範例程式
    http://pydoing.blogspot.com/
    檔名:EncryptDemo.java
    功能:示範 Java 程式 
    作者:張凱慶
    時間:西元 2011 年 4 月 */


我們用到 System.out.print() ,這是另外一個在命令列印出訊息的方法,它與 println() 的差別是不會印出新行符號,也就是 '\n' ,所以最後我們單獨呼叫 print() 印出新行符號。


來編譯執行看看囉



我們可以發現以下這幾組 (a, b) 出現問題
(6, 2) (2, 7) (0, 2) (6, 7) (8, 8)


共通的特點 a 不是 0 就是偶數,所以 a 不能是 0 或偶數嗎?我們繼續改寫 EncryptDemo 進行測試
// 測試 Encrypt 的類別
public class EncryptDemo {
    public static void main(String[] args) {
        System.out.println();
        for (int i = 0; i < 16; i++) {
            Encrypt t = new Encrypt();
            
            // 限定 a 為奇數
            if (t.a % 2 == 0) {
                i--;
                continue;
            }
            
            t.setArray();
            System.out.print(t.cArray);
            System.out.print(", ");
            System.out.print(t.a);
            System.out.print(", ");
            System.out.print(t.b);
            System.out.print("\n");
        }
        System.out.println();
    }
}

/* 《程式語言教學誌》的範例程式
    http://pydoing.blogspot.com/
    檔名:EncryptDemo.java
    功能:示範 Java 程式 
    作者:張凱慶
    時間:西元 2011 年 4 月 */


編譯後執行,如下



這裡
// 限定 a 為奇數
if (t.a % 2 == 0) {
    i--;
    continue;
}


t.a % 2 計算出 a 除以 2 的餘數,如果 a 除以 2 等於 0 ,那麼意味著 a 為 0 或偶數。因此若 t.a % 2 等於 0 ,我們將控制變數 i 遞減 1 ,這等同於取消迴圈的這一輪,然後使用 continue 陳述 (continue statement) ,使迴圈直接進行下一輪。這裡,因為 i 先遞減,然後進入下一輪前, i 會遞增,就會使 i 的值不變,因此仍會印出 16 行結果。


嗯,我們用肉眼檢查,似乎只要 a 為奇數,計算出的結果就不會有問題。因此,公式應修正如下
y = a * x + b // a % 2 != 0
m = y % n
r = m + diff


也就是在 a % 2 不等於 0 之時,公式才成立。嗯,目前我們都是修改 EncryptDemo 進行測試,如果我們希望 Encrypt 更完備,那我們就得回頭修改 Encrypt ,另外, Encrypt 的屬性直接給初值也不是個好的程式設計方式,我們應該把初值設定放在建構子之中。


中英文術語對照
語法錯誤syntax error
執行期間錯誤run-time error
語意錯誤sematic error
編譯器compiler
識別字identifier
例外處理exception handling
類別class
continue 陳述continue statement


您可以繼續參考
軟體開發


相關目錄
回 Java 入門指南
回 Java 教材目錄
回首頁


參考資料
The JavaTM Tutorials: Getting Started
The JavaTM Tutorials: Learning the Java Language
The JavaTM Tutorials: Essential Classes
The Java Language Specification, Third Edition


本文於 2013 年 1 月訂正

1 則留言:

david 提到...

這些也是同樣的線性公式!
如果不預先假設是線性的,解碼似乎會變很困難。。。

Tjivi se lu eduul
Tazmz jv cl vullc
Tinan ph yf hmffy
Tarer dh sv hyvvs
Tgfsf pb ir barri
Tbana kw dm wvmmd
Tfcpc gq lm qnmml
Talyl fd ej dojje